Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

gameserv.c

Go to the documentation of this file.
00001 
00011 /*
00012  * Copyright (c) 1999 James Mulcahy
00013  * All rights reserved.
00014  *
00015  * Redistribution and use in source and binary forms, with or without
00016  * modification, are permitted provided that the following conditions
00017  * are met:
00018  * 1. Redistributions of source code must retain the above copyright
00019  *    notice, this list of conditions and the following disclaimer.
00020  * 2. Redistributions in binary form must reproduce the above copyright
00021  *    notice, this list of conditions and the following disclaimer in the
00022  *    documentation and/or other materials provided with the distribution.
00023  * 3. Neither the name of the authors nor the names of its contributors
00024  *    may be used to endorse or promote products derived from this software
00025  *    without specific prior written permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
00028  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00029  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00030  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
00031  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00032  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00033  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00034  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00035  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00036  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00037  * SUCH DAMAGE.
00038  */
00039 
00040 #include "services.h"
00041 #include "nickserv.h"
00042 #include "chanserv.h"
00043 #include "log.h"
00044 #include "interp.h"
00045 
00049 interp::service_cmd_t gameserv_commands[] = {
00050     /* string             function         Flags      L */
00051     {   "help", gs_help, 0, LOG_NO, 0, 1},
00052     {   "roll", gs_roll, 0, LOG_NO, 0, 1},
00053     {   NULL    },
00054 };
00055 
00056 /*------------------------------------------------------------------------*/
00057 /* Message handler */
00058 
00068 void
00069 sendToGameServ(UserList * nick, char **args, int numargs)
00070 {
00071     char *from = nick->nick;
00072     interp::parser * cmd;
00073 
00074     if (!nick)
00075         return;
00076 
00077     cmd =
00078         new interp::parser(GameServ, getOpFlags(nick), gameserv_commands,
00079                            args[0]);
00080     if (!cmd)
00081         return;
00082 
00083     switch (cmd->run(nick, args, numargs)) {
00084     default:
00085         break;
00086     case RET_FAIL:
00087         sSend(":%s NOTICE %s :Unknown command %s.\r\n"
00088               ":%s NOTICE %s :Please try /msg %s HELP", GameServ, from,
00089               args[0], GameServ, from, GameServ);
00090         break;
00091     }
00092 
00093     delete cmd;
00094 }
00095 
00096 /*------------------------------------------------------------------------*/
00097 /* Utility functions */
00098 
00110 int
00111 dice(int dice, int sides)
00112 {
00113     int res = 0;
00114 
00115     /* Don't bother randomizing if it's always zero */
00116     if (dice < 1 || sides < 1)
00117         return 0;
00118 
00119     /* Roll the dice, sum up the results */
00120     while (dice-- > 0) {
00121         res += 1+(int)(((float)sides * rand()) / (RAND_MAX + 1.0));
00122         /* res += ((random() % sides) + 1); */
00123     }
00124 
00125     return res;
00126 }
00127 
00128 
00129 /*------------------------------------------------------------------------*/
00130 /* Message functions*/
00131 
00135 GCMD(gs_help)
00136 {
00137     char *from = nick->nick;
00138 
00139     help(from, GameServ, args, numargs);
00140     return RET_OK;
00141 }
00142 
00143 
00144 
00151 GCMD(gs_roll)
00152 {
00153     char *from = nick->nick;
00154     char *to = nick->nick;
00155     char *string = args[1];
00156     int rolls = 1;
00157     int num_dice = 1;
00158     int num_sides = 1;
00159     int mod = 0;
00160     int multiplier = 1;         /* +1 or -1 */
00161     int counter = 0;
00162     int i, l = 0, *last_arg = &num_sides;
00163     int result = 0;
00164     char dicebuf[IRCBUF], rollbuf[IRCBUF];
00165     ChanList *chan;
00166 
00167     if (numargs < 2) {
00168         sSend(":%s NOTICE %s :Not enough parameters.\r\n"
00169               ":%s NOTICE %s :/msg %s HELP %s for assistance.", GameServ,
00170               nick->nick, GameServ, nick->nick, GameServ, args[0]);
00171         return RET_SYNTAX;
00172     }
00173 
00174     if (numargs == 3) {
00175         chan = getChanData(args[1]);
00176         if (!chan || !chan->reg) {
00177             sSend(":%s NOTICE %s :%s: No such registered channel is open.",
00178                   GameServ, from, args[1]);
00179             return RET_NOTARGET;
00180         }
00181         if (!getChanUserData(chan, nick)) {
00182             sSend(":%s NOTICE %s :%s: You are not on that channel.",
00183                   GameServ, from, args[1]);
00184             return RET_EFAULT;
00185         }
00186         if (getChanOp(chan->reg, nick->nick) < 4 && !isRoot(nick)) {
00187             sSend
00188                 (":%s NOTICE %s :%s: You must be a channel operator to do this.",
00189                  GameServ, from, args[1]);
00190             return RET_EFAULT;
00191         }
00192         to = args[1];
00193         string = args[2];
00194     }
00195 
00196     /* c#bda+d
00197      * *
00198      * * c is optional.
00199      * * b is optional and defaults to one.
00200      * * a is any integer between 1 and 100 (and %)
00201      * * d is optional, preceded by + or -.
00202      * *
00203      * * Negative numbers are allowed when modified by c.  
00204      * *
00205      * * c is the number of separate outputs to give. ie, 3#1d6 might return: 2, 6, 5
00206      * * b is the number of dice to roll, but not output: 3d6 might return: 13
00207      */
00208     for (i = 0, l = 0; string[i] && (i < 30); i++)
00209         switch (tolower(string[i])) {
00210         case '#':
00211             if (isdigit(*(string + i - l)))
00212                 rolls = atoi(string + i - l);
00213             last_arg = &num_dice;
00214             l = 0;
00215             break;
00216         case 'd':
00217             if (isdigit(*(string + i - l)))
00218                 num_dice = atoi(string + i - l);
00219             last_arg = &num_sides;
00220             l = 0;
00221             break;
00222         case '%':
00223             num_sides = 100;
00224             last_arg = NULL;
00225             l = 0;
00226             break;
00227         case '-':
00228         case '+':
00229             if (string[i] == '-')
00230                 multiplier = -1;
00231             else
00232                 multiplier = 1;
00233             if (isdigit(*(string + i - l)))
00234                 num_sides = atoi(string + i - l);
00235             last_arg = &mod;
00236             l = 0;
00237             break;
00238         default:
00239             l++;
00240             break;
00241         }
00242     if (last_arg != NULL && l) {
00243         if (last_arg == &mod) {
00244             char *p = (string + i - l);
00245 
00246             if (*p == '-' || *p == '+')
00247                 p++;
00248             if (isdigit(*p))
00249                 *last_arg = multiplier * atoi(p);
00250         } else
00251             *last_arg = atoi(string + i - l);
00252     }
00253 
00254     if (*to == '#' && rolls > 10) {
00255         sSend(":%s NOTICE %s :Limited to 10 rolls for channels.", GameServ,
00256               from);
00257         rolls = 10;
00258     }
00259 
00260     if (rolls > 100)
00261         rolls = 100;
00262     if (num_dice > 256)
00263         num_dice = 256;
00264     if (num_sides > 256)
00265         num_sides = 256;
00266     if (mod > 10000)
00267         mod = 10000;
00268     if (mod < -10000)
00269         mod = (-10000);
00270 
00271     /* Seed the rand() with the current time value in microsecs
00272      * if we can't, then use secs */
00273 
00274     dicebuf[0] = rollbuf[0] = '\0';
00275 
00276     for (i = 0, counter = 0; i < rolls; i++) {
00277         result = (dice(num_dice, num_sides) + mod);
00278         if (*dicebuf)
00279             strcpy(rollbuf, ", ");
00280         else
00281             rollbuf[0] = '\0';
00282         sprintf(rollbuf + strlen(rollbuf), "%2d", result);
00283         strcat(dicebuf, rollbuf);
00284         if (counter++ >= 5 || strlen(dicebuf) >= (sizeof(IRCBUF) - 15)) {
00285             if (nick->floodlevel.GetLev() < (.75 * MAXFLOODLEVEL))
00286                 if (addFlood(nick, *to == '#' ? 5 : 1))
00287                     return RET_KILLED;
00288             counter = 0;
00289             if (*to == '#')
00290                 sSend(":%s PRIVMSG %s :Result (%s) (%d#%dd%d%c%d): %s",
00291                       GameServ, to, from, rolls, num_dice, num_sides,
00292                       mod >= 0 ? '+' : '-', abs(mod), dicebuf);
00293             else
00294                 sSend(":%s NOTICE %s :Result (%d#%dd%d%c%d): %s", GameServ,
00295                       to, rolls, num_dice, num_sides, mod >= 0 ? '+' : '-',
00296                       abs(mod), dicebuf);
00297             dicebuf[0] = '\0';
00298         }
00299     }
00300     if (counter) {
00301         if (*to == '#')
00302             sSend(":%s PRIVMSG %s :Result (%s) (%d#%dd%d%c%d): %s",
00303                   GameServ, to, from, rolls, num_dice, num_sides,
00304                   mod >= 0 ? '+' : '-', abs(mod), dicebuf);
00305         else
00306             sSend(":%s NOTICE %s :Result (%d#%dd%d%c%d): %s", GameServ, to,
00307                   rolls, num_dice, num_sides, mod >= 0 ? '+' : '-',
00308                   abs(mod), dicebuf);
00309     }
00310     return RET_OK;
00311 }

Generated at Sat Oct 25 20:56:07 2003 for Services using Doxygen.
Services Copyr. 1996-2001 Chip Norkus, Max Byrd, Greg Poma, Michael Graff, James Hess, Dafydd James. All rights reserved See LICENSE for licensing information.