games-request@tekred.TEK.COM (06/30/87)
Submitted by: Bruce Holloway <drivax!holloway@ames.arpa> Comp.sources.games: Volume 1, Issue 66 Archive-name: roll [I haven't tried this, so you're on your own. -br] #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: README Makefile roll.c # Wrapped by billr@tekred on Mon Jun 29 16:37:32 1987 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f README -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"README\" else echo shar: Extracting \"README\" \(985 characters\) sed "s/^X//" >README <<'END_OF_README' XThe Ultimate Dice Roller! Should be transportable to most systems that Xcan run 'C' and have the standard library. X XThis dice roller is random, even if the random number generator isn't very Xrandom. X XUsage: (options included in braces): X Xroll {numrep@}{{bestroll,}numroll x}{{bestdice,}numdice d}{sides} X Xnumrep [1] = number of times to repeat the rolling sequence. Xbestroll [numroll] = print the best "bestroll" rolls. Xnumroll [1] = number of rolls to do. Xbestdice [numdice] = use the "bestdice" highest rolling dice. Xnumdice [1] = number of dice to use per roll. Xsides [100] = number of sides on the dice. X XExamples: X roll X d100 = 65 X roll 6 X d6 = 3 X roll 4d10 X 4d10 = 11 X roll 5,10d8 X 5,10d8 = 28 X roll 6x3d6 X 6x3d6 = 17 12 11 11 10 6 X roll 6x3,4d6 X 6x3,4d6 = 18 15 10 10 7 6 X roll 5,10x4d4 X 5,10x4d4 = 14 13 12 12 10 X roll 3@6,10x3,4d6 X 6,10x3,4d6 = 17 17 15 15 14 14 X 6,10x3,4d6 = 18 15 15 15 14 14 X 6,10x3,4d6 = 16 14 13 13 11 11 X END_OF_README if test 985 -ne `wc -c <README`; then echo shar: \"README\" unpacked with wrong size! fi # end of overwriting check fi if test -f Makefile -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Makefile\" else echo shar: Extracting \"Makefile\" \(229 characters\) sed "s/^X//" >Makefile <<'END_OF_Makefile' X# Makefile for ROLL X# X# Comment out the BSD line if you're on System V X# Comment out the SYSV line if you're using Berkely Unix. X X# SYSTEM = -DSYSV XSYSTEM = -DBSD X XCFLAGS = -O $(SYSTEM) X Xroll: roll.c X cc -o roll $(CFLAGS) roll.c END_OF_Makefile if test 229 -ne `wc -c <Makefile`; then echo shar: \"Makefile\" unpacked with wrong size! fi # end of overwriting check fi if test -f roll.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"roll.c\" else echo shar: Extracting \"roll.c\" \(7305 characters\) sed "s/^X//" >roll.c <<'END_OF_roll.c' X/***************************************************************************** X* ROLL - Rolls dice - lots of them - and really randomly. X* X* X* Usage: (options included in braces): X* X* roll {numrep@}{{bestroll,}numroll x}{{bestdice,}numdice d}{sides} X* X* numrep [1] = number of times to repeat the rolling sequence. X* bestroll [numroll] = print the best "bestroll" rolls. X* numroll [1] = number of rolls to do. X* bestdice [numdice] = use the "bestdice" highest rolling dice. X* numdice [1] = number of dice to use per roll. X* sides [100] = number of sides on the dice. X* X* Examples: X* roll X* d100 = 65 X* roll 6 X* d6 = 3 X* roll 4d10 X* 4d10 = 11 X* roll 5,10d8 X* 5,10d8 = 28 X* roll 6x3d6 X* 6x3d6 = 17 12 11 11 10 6 X* roll 6x3,4d6 X* 6x3,4d6 = 18 15 10 10 7 6 X* roll 5,10x4d4 X* 5,10x4d4 = 14 13 12 12 10 X* roll 3@6,10x3,4d6 X* 6,10x3,4d6 = 17 17 15 15 14 14 X* 6,10x3,4d6 = 18 15 15 15 14 14 X* 6,10x3,4d6 = 16 14 13 13 11 11 X******************************************************************************/ X X#include <stdio.h> X#include <ctype.h> X X#define NUMREDUX 5 X X#ifdef SYSV X#define index strchr X#define rindex strrchr X#define srandom srand X#define random rand X#endif X Xextern char *index(), *rindex(); Xextern char *malloc(); Xextern void free(); X Xint numroll = 1, bestroll = 1; /* Number of rolls to roll and keep */ Xint numdice = 1, bestdice = 1; /* Number of dice to roll and keep */ Xint sides = 100; /* Number of sides on each die */ X Xint *ar_rolls; /* Array of rolls */ Xint *ar_dice; /* Array of dice */ Xint *ar_side; /* Array of side data */ X Xchar *show(); /* Routine to format output */ X Xchar iline[80]; /* To parse the roll */ Xchar aroll[80]; /* When rolls are repeated */ X Xmain(acnt,avar) Xint acnt; Xchar *avar[]; X{ X int i, j, k, val; X char *s, *s1; X X/* if(acnt < 2){ X printf("usage: roll {numroll x }{numdice d }{numsides}\n"); X printf("\tExample: roll 100 ; roll 3d8 ; roll 6x3d8\n"); X return; X } X*/ X srandom(time(0L)); /* Randomize */ X X if(acnt <= 1) /* Default: Roll 1d100 */ X roll(""); X else X for(i=0; ++i < acnt;){ /* For each argument */ X s = avar[i]; X if(s1 = index(s,'@')){ /* Repeat the roll? */ X *s1 = 0; X j = atoi(s); /* Get repetition */ X if(j < 1){ X printf("roll: Repetition count must be greater than zero.\n"); X return; X } X s = s1+1; /* Advance pointer past it */ X } X else j = 1; /* Default: Only one time. */ X strcpy(aroll,s); /* Save it. */ X while(j--){ X strcpy(s,aroll); X roll(s); /* Do the roll */ X } X } X} X Xroll(inline) Xchar *inline; X{ X int i, j, k, val, r; X char *s, *s1; X X numroll = bestroll = bestdice = numdice = 1; /* Set defaults. */ X sides = 100; X X for(s=inline; *s; ++s) /* Convert to lower case */ X if(isupper(*s)) X *s = tolower(*s); X X s = inline; X if(s1 = index(s,'x')){ /* Get number of rolls */ X *s1 = 0; X parse(s,&numroll,&bestroll); X s = s1+1; X } X if(s1 = index(s,'d')){ /* Get number of dice */ X *s1 = 0; X parse(s,&numdice,&bestdice); X s = s1+1; X } X if(*s) sides = atoi(s); /* get number of sides */ X X if(error()) return; /* Check sanity */ X X if(numroll > 1) printf("%sx",show(iline,bestroll,numroll)); X if(numdice > 1) printf("%s",show(iline,bestdice,numdice)); X printf("d%d = ",sides); X fflush(stdout); /* Echo the command */ X X/* Allocate the arrays - one to keep all the rolls, one to keep each roll X by the die roll, and one to make sure the dice are rolled RANDOMLY. X*/ X ar_rolls = (int *)malloc(sizeof(int) * numroll); X ar_dice = (int *)malloc(sizeof(int) * numdice); X ar_side = (int *)malloc(sizeof(int) * NUMREDUX * sides); X X/* Get out if we couldn't allocate the arrays */ X X if(!ar_rolls || !ar_dice || !ar_side){ X printf("*** Out of memory ***\n"); X if(ar_rolls) free(ar_rolls); X if(ar_dice) free(ar_dice); X if(ar_side) free(ar_side); X return; X } X X/* Make an array filled with the possible side values. Several times. So X that even if the random number generator isn't completely random, it X has a chance to produce random values when indexing into the array. X*/ X for(i=j=0; i<NUMREDUX; ++i) X for(k=0; k++ < sides; ++j) X *(ar_side+j) = k; X X/* Randomize the array - necessary to catch cyclic random number generators. */ X X for(i=0; i < NUMREDUX * sides; ++i){ X r = random(); X if(r < 0) r = -r; X r %= NUMREDUX * sides; X j = *(ar_side+i); X *(ar_side+i) = *(ar_side+r); X *(ar_side+r) = j; X } X X for(i = 0; i<numroll; ++i){ /* For each roll */ X for(j=0; j<numdice; ++j){ /* For each die */ X r = random(); /* Roll the die */ X if(r < 0) r = -r; X *(ar_dice+j) = *(ar_side + (r % (sides * NUMREDUX))); X } X if(bestdice < numdice) sort(ar_dice,numdice); /* Get the best 'n' */ X for(j=val=0; j<bestdice; ++j) /* Sum them to get the roll */ X val += *(ar_dice+j); X *(ar_rolls+i) = val; X } X sort(ar_rolls,numroll); /* Sort the rolls */ X for(i=0; i<bestroll; ++i) /* And print out the best 'n' */ X printf("%d ",*(ar_rolls+i)); X printf("\n"); X X free(ar_rolls); /* Free all the arrays */ X free(ar_dice); X free(ar_side); X} X X/***************************************************************************** X* PARSE X* X* Figure out strings that look like "ddd" and "ddd,ddd", and fill in X* the values nicely. Handle defaults, too. X******************************************************************************/ X Xparse(s,n,b) Xchar *s; Xint *n, *b; X{ X char *s1; X X if(s1 = index(s,',')){ X *s1 = 0; X *b = atoi(s); X *n = atoi(s1+1); X } X else *b = *n = atoi(s); X} X X/***************************************************************************** X* SORT X* X* Bubble sort (yech) an array. X******************************************************************************/ X Xsort(a,n) Xint a[], n; X{ X int changed, i, t; X X if(n <= 1) return; X X for(changed=1; changed;){ X changed = 0; X for(i=0; i<n-1; ++i){ X if(a[i] < a[i+1]){ X changed = 1; X t = a[i]; a[i] = a[i+1]; a[i+1] = t; X } X } X } X} X X/***************************************************************************** X* ERROR X* X* Scan and report any errors. X******************************************************************************/ X Xerror(){ X int iserr=0; X X if(numroll <= 0){ X fprintf(stderr,"roll: Number of rolls must be greater than zero.\n"); X ++iserr; X } X X if(bestroll < 1 || bestroll > numroll){ X fprintf(stderr,"roll: Number of rolls to keep must be greater than zero,\n"); X fprintf(stderr," less than the total number of rolls.\n"); X ++iserr; X } X X if(numdice <= 0){ X fprintf(stderr,"roll: Number of dice to roll must be greater than zero.\n"); X ++iserr; X } X X if(bestdice < 1 || bestdice > numdice){ X fprintf(stderr,"roll: Number of dice to keep must be greater than zero,\n"); X fprintf(stderr," less than the number of dice.\n"); X ++iserr; X } X X if(sides <= 1){ X fprintf(stderr,"roll: Dice must have at least two sides.\n"); X ++iserr; X } X X return(iserr); X} X X/***************************************************************************** X* SHOW X* X* Format some output. X******************************************************************************/ X Xchar *show(s,b,n) Xchar *s; Xint b, n; X{ X if(b == n) X sprintf(s,"%d",n); X else X sprintf(s,"%d,%d",b,n); X return(s); X} END_OF_roll.c if test 7305 -ne `wc -c <roll.c`; then echo shar: \"roll.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0