# # Patch name: dicefun # Patch version: 1.0 # Author's name: Michael Kelly # Author's email: kellym@nbnet.nb.ca # Version of PennMUSH: 1.7.2p10 # Date patch made: April 18 # Author is willing to support (yes/no): yes # Patch format: context diff # # # This is a contributed PennMUSH patch. Its use is subject to the # same restrictions found in PennMUSH's hdrs/copyrite.h file. # # No warranty is given for this patch. It is not necessarily going # to work on your system, with any version of PennMUSH other than # the one above, etc. # # If the author given above was willing to support the patch, you # should write to the author if you have any questions or problems. Do # *NOT* send email messages to Javelin or any PennMUSH mailing list about # this patch! # # Below this line is the author's description of the patch, # followed by the patch itself. If the patch is in context diff # format, you'll probably apply it by typing: patch < patchfile # in your top-level MUSH directory, unless instructed otherwise # below. # Basically what this does is it adds 3 functions to your PennMUSH server(die_add, die_sub, die_gle), modifies the die() function to conform to a newer behavior, and adds/changes the help information for all of these. Now, you can use dice of the format DIEDSIDES+PIPS or DIED+PIP and add then together(just like that), subtract one from another, or compare them(greater then, less then, equal to). The modifications to die() set it up to roll dice of that format. diff -cN ../tmp/src/Makefile src/Makefile *** ../tmp/src/Makefile Sun Apr 26 10:49:57 1998 --- src/Makefile Sun Apr 26 09:51:27 1998 *************** *** 36,42 **** match.c memcheck.c move.c parse.c player.c plyrlist.c \ predicat.c privtab.c regexp.c \ rob.c rpage.c rwho.c services.c set.c speech.c strdup.c \ ! strutil.c timer.c unparse.c utils.c version.c warnings.c wild.c wiz.c H_FILES = ../hdrs/attrib.h ../hdrs/conf.h ../hdrs/copyrite.h ../hdrs/mushdb.h \ ../hdrs/flags.h ../hdrs/externs.h ../hdrs/globals.h \ --- 36,43 ---- match.c memcheck.c move.c parse.c player.c plyrlist.c \ predicat.c privtab.c regexp.c \ rob.c rpage.c rwho.c services.c set.c speech.c strdup.c \ ! strutil.c timer.c unparse.c utils.c version.c warnings.c wild.c wiz.c \ ! dice.c H_FILES = ../hdrs/attrib.h ../hdrs/conf.h ../hdrs/copyrite.h ../hdrs/mushdb.h \ ../hdrs/flags.h ../hdrs/externs.h ../hdrs/globals.h \ *************** *** 47,53 **** ../hdrs/version.h ../hdrs/getpgsiz.h ../hdrs/regexp.h \ ../config.h ../confmagic.h ../hdrs/function.h ../hdrs/parse.h \ ../hdrs/extmail.h ../hdrs/extchat.h \ ! ../hdrs/htab.h ../hdrs/command.h ../hdrs/htab.h ../hdrs/privtab.h # .o versions of above - these are used in the build O_FILES= \ --- 48,55 ---- ../hdrs/version.h ../hdrs/getpgsiz.h ../hdrs/regexp.h \ ../config.h ../confmagic.h ../hdrs/function.h ../hdrs/parse.h \ ../hdrs/extmail.h ../hdrs/extchat.h \ ! ../hdrs/htab.h ../hdrs/command.h ../hdrs/htab.h ../hdrs/privtab.h \ ! ../hdrs/dice.h # .o versions of above - these are used in the build O_FILES= \ *************** *** 110,116 **** version.o \ warnings.o \ wild.o \ ! wiz.o # This is a dummy target, in case you type 'make' in the source --- 112,119 ---- version.o \ warnings.o \ wild.o \ ! wiz.o \ ! dice.o # This is a dummy target, in case you type 'make' in the source diff -cN ../tmp/src/function.c src/function.c *** ../tmp/src/function.c Sun Apr 26 10:49:57 1998 --- src/function.c Sun Apr 26 09:51:27 1998 *************** *** 148,154 **** {"DECRYPT", fun_decrypt, 2, 2, FN_REG}, {"DEFAULT", fun_default, 2, 2, FN_NOPARSE}, {"DELETE", fun_delete, 3, 3, FN_REG}, ! {"DIE", fun_die, 2, 2, FN_REG}, {"DIG", fun_dig, 1, 3, FN_REG}, {"DIST2D", fun_dist2d, 4, 4, FN_REG}, {"DIST3D", fun_dist3d, 6, 6, FN_REG}, --- 148,157 ---- {"DECRYPT", fun_decrypt, 2, 2, FN_REG}, {"DEFAULT", fun_default, 2, 2, FN_NOPARSE}, {"DELETE", fun_delete, 3, 3, FN_REG}, ! {"DIE", fun_die, 1, 1, FN_REG}, ! {"DIE_ADD", fun_die_add, 2, 2, FN_REG}, ! {"DIE_SUB", fun_die_sub, 2, 2, FN_REG}, ! {"DIE_GLE", fun_die_gle, 2, 2, FN_REG}, {"DIG", fun_dig, 1, 3, FN_REG}, {"DIST2D", fun_dist2d, 4, 4, FN_REG}, {"DIST3D", fun_dist3d, 6, 6, FN_REG}, diff -cN ../tmp/src/funlocal.c src/funlocal.c *** ../tmp/src/funlocal.c Sun Apr 26 10:53:37 1998 --- src/funlocal.c Sun Apr 26 09:51:27 1998 *************** *** 26,36 **** --- 26,70 ---- #include "function.h" void local_functions _((void)); + extern char *as_die(char *die_exp1, char *die_exp2, int op); + extern int gle_die(char *die_exp1, char *die_exp2); /* Here you can use the new add_function instead of hacking into function.c * Example included :) */ + FUNCTION(fun_die_add) + { + char *res; + + res = as_die(args[0], args[1], 0); + if (!res) + safe_str("#-1 BAD DIE EXPRESSION(S)", buff, bp); + else + safe_str(res, buff, bp); + free(res); + } + FUNCTION(fun_die_sub) + { + char *res; + res = as_die(args[0], args[1], 1); + if (!res) + safe_str("#-1 BAD DIE EXPRESSION(S)", buff, bp); + else + safe_str(res, buff, bp); + free(res); + } + + FUNCTION(fun_die_gle) + { + int res; + + res = gle_die(args[0], args[1]); + if (res == -2 || res == -3) + safe_str("#-1 BAD DIE EXPRESSION(S)", buff, bp); + else + safe_str(unparse_integer(res), buff, bp); + } #ifdef EXAMPLE FUNCTION(local_fun_silly) { diff -cN ../tmp/src/funmisc.c src/funmisc.c *** ../tmp/src/funmisc.c Sun Apr 26 10:49:57 1998 --- src/funmisc.c Sun Apr 26 09:51:27 1998 *************** *** 16,26 **** --- 16,28 ---- #include "parse.h" #include "function.h" #include "confmagic.h" + #include "dice.h" #ifdef WIN32 #pragma warning( disable : 4761) /* NJG: disable warning re conversion */ #endif + extern DIE *break_die(char *die_exp); extern time_t start_time; extern FUN flist[]; static char *soundex _((char *str)); *************** *** 172,196 **** /* ARGSUSED */ FUNCTION(fun_die) { - int n; int die; int count; int total = 0; ! if (!is_integer(args[0]) || !is_integer(args[1])) { ! safe_str(e_ints, buff, bp); return; } - n = parse_integer(args[0]); - die = parse_integer(args[1]); ! if ((n < 0) || (n > 20)) { safe_str("#-1 NUMBER OUT OF RANGE", buff, bp); return; } - for (count = 0; count < n; count++) - total += getrandom(die) + 1; safe_str(unparse_integer(total), buff, bp); } --- 174,207 ---- /* ARGSUSED */ FUNCTION(fun_die) { int die; int count; int total = 0; + DIE *x; ! /* break down expression */ ! if (!(x = break_die(args[0]))) { ! safe_str("#-1 BAD DIE EXPRESSION", buff, bp); return; } ! /* test dice */ ! if ((x->dice < 0) || (x->dice > 20)) { ! safe_str("#-1 NUMBER OUT OF RANGE", buff, bp); ! return; ! } ! if ((x->sides < 2) || (x->sides > 20)) { safe_str("#-1 NUMBER OUT OF RANGE", buff, bp); return; } + /* do the rolls */ + for (count = 0; count < x->dice; count++) + total += getrandom(x->sides) + 1; + + /* add in the pips */ + total += x->pip; + free(x); /* free up x */ safe_str(unparse_integer(total), buff, bp); } diff -cN ../tmp/hdrs/dice.h hdrs/dice.h *** ../tmp/hdrs/dice.h Wed Dec 31 20:00:00 1969 --- hdrs/dice.h Sun Apr 26 09:51:27 1998 *************** *** 0 **** --- 1,5 ---- + /* Type declaration for 'DIE'(dice), we use this to contain our stuff */ + typedef struct die_set { + int dice, pip, sides; + } DIE; + diff -cN ../tmp/game/txt/hlp/pennfunc.hlp game/txt/hlp/pennfunc.hlp *** ../tmp/game/txt/hlp/pennfunc.hlp Sun Apr 26 10:49:57 1998 --- game/txt/hlp/pennfunc.hlp Sun Apr 26 09:51:27 1998 *************** *** 165,178 **** These functions don't quite fit into any other category. ansi() atrlock() beep() cemit() convsecs() ! convtime() clone() create() die() dig() ! emit() functions() isdaylight() isdbref() isnum() ! isword() lemit() link() lnum() mudname() ! objeval() oemit() open() pemit() r-function ! rand() remit() s-function secs() set() ! setq() setr() soundex() soundslike() starttime() ! tel() time() timestring() valid() version() ! wipe() zemit() & ABS() abs() --- 165,178 ---- These functions don't quite fit into any other category. ansi() atrlock() beep() cemit() convsecs() ! convtime() clone() create() die() die_add() ! die_gle() die_sub() dig() emit() functions() ! isdaylight() isdbref() isnum() isword() lemit() ! link() lnum() mudname() objeval() oemit() ! open() pemit() r-function rand() remit() ! s-function secs() set() setq() setr() ! soundex() soundslike() starttime() tel() time() ! timestring() valid() version() wipe() zemit() & ABS() abs() *************** *** 501,512 **** You say, "abcfgh" & DIE() ! die(, ) This function simulates rolling dice. It "rolls" a die with a given number of sides, a certain number of times, and sums the results. ! For example, DIE(2, 6) would roll "2d6" - two six-sided dice, ! generating a result in the range 2-12. & DIG() dig(, , ) --- 501,555 ---- You say, "abcfgh" & DIE() ! die() + A DICEDSIDES+PIP expression is an expression such as 1D6+2. The SIDES + section is equal to 6 if omitted. + This function simulates rolling dice. It "rolls" a die with a given number of sides, a certain number of times, and sums the results. ! For example, DIE(2D6+0) would roll "2d6" - two six-sided dice, ! generating a result in the range 2-12. die() only supports expressions ! with 0-20 dice, and 2-20 sides. ! ! & DIE_ADD() ! die_add(, ) ! ! A DICEDSIDES+PIP expression is an expression such as 1D6+2. The SIDES ! section is equal to 6 if omitted. ! ! This function adds 2 pairs of dice together, returning a new total. ! Example: ! > think die_add(1D6+1, 2D6+2) ! 4D6+0 ! ! & DIE_SUB() ! die_sub(, ) ! ! A DICEDSIDES+PIP expression is an expression such as 1D6+2. The SIDES ! section is equal to 6 if omitted. ! ! This function subtracts the second dice from the first dice, returning a ! new total. ! Example: ! > think die_sub(3D6+1, 2D6+2) ! 1D6+1 ! ! & DIE_GLE() ! die_gle(, ) ! ! A DICEDSIDES+PIP expression is an expression such as 1D6+2. The SIDES ! section is equal to 6 if omitted. ! ! This function returns: ! 0 if the 2 expressions are equal ! -1 if the second expression is 'greater then' the first ! 1 if the second expression is less then the first ! ! Example: ! > think die_gle(1D+0, 2D+0) ! -1 ! & DIG() dig(, , ) diff -cN ../penn2/src/dice.c src/dice.c *** ../penn2/src/dice.c Wed Dec 31 20:00:00 1969 --- src/dice.c Mon Apr 27 22:23:33 1998 *************** *** 0 **** --- 1,244 ---- + #include + #include + #include + #include "dice.h" + + int good_die(char *die_exp); + DIE *break_die(char *die_exp); + char *as_die(char *die_exp1, char *die_exp2, int op); + char *make_die(DIE *die_info); + int gle_die(char *die_exp1, char *die_exp2); + + /* This basic code is to be used to perfrom the basic arithmetic functions + using DIEDSIDES+PIP expressions. Basic arithmetic expressions are: + ADD + SUBTRACT + GREATER THEN + LESS THEN + EQUAL TO + */ + + + int + good_die(char *die_exp) + { + int x = 0, y = 0; + + if (*die_exp == '-') /* check for negative */ + die_exp++; + + while (*die_exp != '\0') { + if (y > 0) { /* we're looking for a + */ + if ((*die_exp < 48 || *die_exp > 58) && *die_exp != '+') + return -1; + else if (*die_exp == '+') + y = -1; + } else if (y == 0) { /* we're looking for a D */ + if ((*die_exp < 48 || *die_exp > 58) && (*die_exp != 'D' && *die_exp != 'd')) + return -1; + else if ((*die_exp == 'D' || *die_exp == 'd') && x == 0) + return -1; + else if ((*die_exp == 'D' || *die_exp == 'd') && x != 0) { + x = 0; + y = 1; + } else + x++; + } else if (y < 0) { /* we're looking for NULL */ + if ((*die_exp < 48 || *die_exp > 58) && *die_exp != '\0') + return -1; + else if (*die_exp == '\0' && x == 0) + return -1; + else + x++; + } + die_exp++; + } + if (y > -1 || x == 0) + return -1; + + return 0; /* it's a good one */ + } + + /* use this to break down the expression into it's componenets */ + DIE * + break_die(char *die_exp) + { + DIE *die = NULL; + char *die_exp2 = NULL, *k, *m; + int n; + + /* verify our die expression */ + if (good_die(die_exp)) + return NULL; + + n = strlen(die_exp); + + /* do the mallocation */ + die = (DIE *) malloc(1 * sizeof(DIE)); + die_exp2 = (char *) malloc(n * sizeof(char)); + if (!die || !die_exp2) + return '\0'; + + strcpy(die_exp2, die_exp); /* copy the string */ + die_exp2[n] = '\0'; + + /* locate # of dice */ + k = die_exp2; + while (*k != 'D' && *k != 'd') + k++; + + k[0] = '\0'; /* nullify the D */ + die->dice = atoi(die_exp2); /* set the dice value */ + + k[0] = 'D'; + k++; /* move ahead */ + m = k; + + /* locate sides */ + n = 0; + while (*k != '+') { + n++; + k++; + } + /* if n > 1 we have a # of sides supplied, if not, it's 6 */ + if (n > 1) { + k[0] = '\0'; + die->sides = atoi(m); + + k[0] = '+'; + } else { + die->sides = 6; + } + + k++; /* move ahead */ + + if (*k) /* make sure we have pips */ + die->pip = atoi(k); /* get pips */ + free(die_exp2); /* free up the memory we used */ + + /* now sort em out so we don't have a pip greater then 2 */ + while (die->pip > 2) { + die->pip -= 3; + die->dice += 1; + } + while (die->pip < 0) { + die->pip += 3; + die->dice -= 1; + } + + return die; + } + + char * + as_die(char *die_exp1, char *die_exp2, int op) + { + DIE *de1, *de2; + char *new_de; + + /* break expression 1 */ + if (!(de1 = break_die(die_exp1))) + return NULL; + + /* break expression 2 */ + if (!(de2 = break_die(die_exp2))) + return NULL; + + /* make sure both dice have the same # of sides */ + if (de2->sides != de1->sides) + return NULL; + + /* do the basic math up */ + if (op == 0) { + de1->dice += de2->dice; + de1->pip += de2->pip; + } else { + de1->dice -= de2->dice; + de1->pip -= de2->pip; + } + + /* now sort em out so we don't have a pip greater then 2 */ + while (de1->pip > 2) { + de1->pip -= 3; + de1->dice += 1; + } + while (de1->pip < 0) { + de1->pip += 3; + de1->dice -= 1; + } + + new_de = make_die(de1); /* make the new exp */ + free(de1); /* we no longer need the first one */ + free(de2); /* we no longer need the second one */ + + return new_de; + } + + char * + make_die(DIE *die_info) + { + char *die_result = NULL; + char *x_block; + int x = 0; + + if (die_info) + die_result = (char *) malloc(40 * sizeof(char)); + if (!die_result) + return die_result; + + /* assemble result */ + sprintf(die_result, "%iD%i+%i\n", + die_info->dice, die_info->sides, die_info->pip); + x_block = die_result; + /* determine length of result */ + while(*x_block != '\n') { + x_block++; + x++; + } + /* copy it to a shorter string */ + x_block = (char *) malloc(x * sizeof(char)); + if (!x_block) { + free(die_result); + return x_block; + } + /* do copy */ + strncpy(x_block, die_result, x); + x_block[x] = '\0'; + free(die_result); /* free first malloc */ + + return x_block; + } + + /* return 0 if equal, + return -1 if die_exp1 < die_exp2, + return 1 if die_exp1 > die_exp2, + */ + int + gle_die(char *die_exp1, char *die_exp2) + { + DIE *de1, *de2; + + if (!die_exp1 || !die_exp2) /* make sure we have em both */ + return -2; + + if (!(de1 = break_die(die_exp1))) + return -3; /* make sure we get a properly broken dice) */ + if (!(de2 = break_die(die_exp2))) + return -3; /* make sure we get another properly broken die */ + + if (de1->dice > de2->dice) /* greather then */ + return 1; + else if (de1->dice < de2->dice) /* less then */ + return -1; + else if (de1->dice == de2->dice) { + if (de1->pip > de2->pip) /* greater then */ + return 1; + else if (de1->pip < de2->pip) /* less then */ + return -1; + else if (de1->pip == de2->pip)/* equal */ + return 0; + } + + free(de1); /* free up our pointers */ + free(de2); + return -4; /* we should never reach this condition */ + }