DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T r

⟦39054b95d⟧ TextFile

    Length: 7305 (0x1c89)
    Types: TextFile
    Names: »roll.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Roll/roll.c« 

TextFile

/*****************************************************************************
*	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);
}