|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 7305 (0x1c89) Types: TextFile Names: »roll.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Roll/roll.c«
/***************************************************************************** * ROLL - Rolls dice - lots of them - and really randomly. * * * Usage: (options included in braces): * * roll {numrep@}{{bestroll,}numroll x}{{bestdice,}numdice d}{sides} * * numrep [1] = number of times to repeat the rolling sequence. * bestroll [numroll] = print the best "bestroll" rolls. * numroll [1] = number of rolls to do. * bestdice [numdice] = use the "bestdice" highest rolling dice. * numdice [1] = number of dice to use per roll. * sides [100] = number of sides on the dice. * * Examples: * roll * d100 = 65 * roll 6 * d6 = 3 * roll 4d10 * 4d10 = 11 * roll 5,10d8 * 5,10d8 = 28 * roll 6x3d6 * 6x3d6 = 17 12 11 11 10 6 * roll 6x3,4d6 * 6x3,4d6 = 18 15 10 10 7 6 * roll 5,10x4d4 * 5,10x4d4 = 14 13 12 12 10 * roll 3@6,10x3,4d6 * 6,10x3,4d6 = 17 17 15 15 14 14 * 6,10x3,4d6 = 18 15 15 15 14 14 * 6,10x3,4d6 = 16 14 13 13 11 11 ******************************************************************************/ #include <stdio.h> #include <ctype.h> #define NUMREDUX 5 #ifdef SYSV #define index strchr #define rindex strrchr #define srandom srand #define random rand #endif extern char *index(), *rindex(); extern char *malloc(); extern void free(); int numroll = 1, bestroll = 1; /* Number of rolls to roll and keep */ int numdice = 1, bestdice = 1; /* Number of dice to roll and keep */ int sides = 100; /* Number of sides on each die */ int *ar_rolls; /* Array of rolls */ int *ar_dice; /* Array of dice */ int *ar_side; /* Array of side data */ char *show(); /* Routine to format output */ char iline[80]; /* To parse the roll */ char aroll[80]; /* When rolls are repeated */ main(acnt,avar) int acnt; char *avar[]; { int i, j, k, val; char *s, *s1; /* if(acnt < 2){ printf("usage: roll {numroll x }{numdice d }{numsides}\n"); printf("\tExample: roll 100 ; roll 3d8 ; roll 6x3d8\n"); return; } */ srandom(time(0L)); /* Randomize */ if(acnt <= 1) /* Default: Roll 1d100 */ roll(""); else for(i=0; ++i < acnt;){ /* For each argument */ s = avar[i]; if(s1 = index(s,'@')){ /* Repeat the roll? */ *s1 = 0; j = atoi(s); /* Get repetition */ if(j < 1){ printf("roll: Repetition count must be greater than zero.\n"); return; } s = s1+1; /* Advance pointer past it */ } else j = 1; /* Default: Only one time. */ strcpy(aroll,s); /* Save it. */ while(j--){ strcpy(s,aroll); roll(s); /* Do the roll */ } } } roll(inline) char *inline; { int i, j, k, val, r; char *s, *s1; numroll = bestroll = bestdice = numdice = 1; /* Set defaults. */ sides = 100; for(s=inline; *s; ++s) /* Convert to lower case */ if(isupper(*s)) *s = tolower(*s); s = inline; if(s1 = index(s,'x')){ /* Get number of rolls */ *s1 = 0; parse(s,&numroll,&bestroll); s = s1+1; } if(s1 = index(s,'d')){ /* Get number of dice */ *s1 = 0; parse(s,&numdice,&bestdice); s = s1+1; } if(*s) sides = atoi(s); /* get number of sides */ if(error()) return; /* Check sanity */ if(numroll > 1) printf("%sx",show(iline,bestroll,numroll)); if(numdice > 1) printf("%s",show(iline,bestdice,numdice)); printf("d%d = ",sides); fflush(stdout); /* Echo the command */ /* Allocate the arrays - one to keep all the rolls, one to keep each roll by the die roll, and one to make sure the dice are rolled RANDOMLY. */ ar_rolls = (int *)malloc(sizeof(int) * numroll); ar_dice = (int *)malloc(sizeof(int) * numdice); ar_side = (int *)malloc(sizeof(int) * NUMREDUX * sides); /* Get out if we couldn't allocate the arrays */ if(!ar_rolls || !ar_dice || !ar_side){ printf("*** Out of memory ***\n"); if(ar_rolls) free(ar_rolls); if(ar_dice) free(ar_dice); if(ar_side) free(ar_side); return; } /* Make an array filled with the possible side values. Several times. So that even if the random number generator isn't completely random, it has a chance to produce random values when indexing into the array. */ for(i=j=0; i<NUMREDUX; ++i) for(k=0; k++ < sides; ++j) *(ar_side+j) = k; /* Randomize the array - necessary to catch cyclic random number generators. */ for(i=0; i < NUMREDUX * sides; ++i){ r = random(); if(r < 0) r = -r; r %= NUMREDUX * sides; j = *(ar_side+i); *(ar_side+i) = *(ar_side+r); *(ar_side+r) = j; } for(i = 0; i<numroll; ++i){ /* For each roll */ for(j=0; j<numdice; ++j){ /* For each die */ r = random(); /* Roll the die */ if(r < 0) r = -r; *(ar_dice+j) = *(ar_side + (r % (sides * NUMREDUX))); } if(bestdice < numdice) sort(ar_dice,numdice); /* Get the best 'n' */ for(j=val=0; j<bestdice; ++j) /* Sum them to get the roll */ val += *(ar_dice+j); *(ar_rolls+i) = val; } sort(ar_rolls,numroll); /* Sort the rolls */ for(i=0; i<bestroll; ++i) /* And print out the best 'n' */ printf("%d ",*(ar_rolls+i)); printf("\n"); free(ar_rolls); /* Free all the arrays */ free(ar_dice); free(ar_side); } /***************************************************************************** * PARSE * * Figure out strings that look like "ddd" and "ddd,ddd", and fill in * the values nicely. Handle defaults, too. ******************************************************************************/ parse(s,n,b) char *s; int *n, *b; { char *s1; if(s1 = index(s,',')){ *s1 = 0; *b = atoi(s); *n = atoi(s1+1); } else *b = *n = atoi(s); } /***************************************************************************** * SORT * * Bubble sort (yech) an array. ******************************************************************************/ sort(a,n) int a[], n; { int changed, i, t; if(n <= 1) return; for(changed=1; changed;){ changed = 0; for(i=0; i<n-1; ++i){ if(a[i] < a[i+1]){ changed = 1; t = a[i]; a[i] = a[i+1]; a[i+1] = t; } } } } /***************************************************************************** * ERROR * * Scan and report any errors. ******************************************************************************/ error(){ int iserr=0; if(numroll <= 0){ fprintf(stderr,"roll: Number of rolls must be greater than zero.\n"); ++iserr; } if(bestroll < 1 || bestroll > numroll){ fprintf(stderr,"roll: Number of rolls to keep must be greater than zero,\n"); fprintf(stderr," less than the total number of rolls.\n"); ++iserr; } if(numdice <= 0){ fprintf(stderr,"roll: Number of dice to roll must be greater than zero.\n"); ++iserr; } if(bestdice < 1 || bestdice > numdice){ fprintf(stderr,"roll: Number of dice to keep must be greater than zero,\n"); fprintf(stderr," less than the number of dice.\n"); ++iserr; } if(sides <= 1){ fprintf(stderr,"roll: Dice must have at least two sides.\n"); ++iserr; } return(iserr); } /***************************************************************************** * SHOW * * Format some output. ******************************************************************************/ char *show(s,b,n) char *s; int b, n; { if(b == n) sprintf(s,"%d",n); else sprintf(s,"%d,%d",b,n); return(s); }