home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume1 / roll / roll.c < prev   
C/C++ Source or Header  |  1987-06-29  |  7KB  |  294 lines

  1. /*****************************************************************************
  2. *    ROLL - Rolls dice - lots of them - and really randomly.
  3. *
  4. *
  5. *    Usage: (options included in braces):
  6. *
  7. *    roll {numrep@}{{bestroll,}numroll x}{{bestdice,}numdice d}{sides}
  8. *
  9. *    numrep   [1]       = number of times to repeat the rolling sequence.
  10. *    bestroll [numroll] = print the best "bestroll" rolls.
  11. *    numroll  [1]       = number of rolls to do.
  12. *    bestdice [numdice] = use the "bestdice" highest rolling dice.
  13. *    numdice  [1]       = number of dice to use per roll.
  14. *    sides    [100]     = number of sides on the dice.
  15. *
  16. *    Examples:
  17. *        roll
  18. *            d100 = 65 
  19. *        roll 6
  20. *            d6 = 3 
  21. *        roll 4d10
  22. *            4d10 = 11 
  23. *        roll 5,10d8
  24. *            5,10d8 = 28 
  25. *        roll 6x3d6
  26. *            6x3d6 = 17 12 11 11 10 6 
  27. *        roll 6x3,4d6
  28. *            6x3,4d6 = 18 15 10 10 7 6 
  29. *        roll 5,10x4d4
  30. *            5,10x4d4 = 14 13 12 12 10 
  31. *        roll 3@6,10x3,4d6
  32. *            6,10x3,4d6 = 17 17 15 15 14 14 
  33. *            6,10x3,4d6 = 18 15 15 15 14 14 
  34. *            6,10x3,4d6 = 16 14 13 13 11 11 
  35. ******************************************************************************/
  36.  
  37. #include <stdio.h>
  38. #include <ctype.h>
  39.  
  40. #define    NUMREDUX    5
  41.  
  42. #ifdef SYSV
  43. #define    index    strchr
  44. #define    rindex    strrchr
  45. #define    srandom    srand
  46. #define    random    rand
  47. #endif
  48.  
  49. extern char *index(), *rindex();
  50. extern char *malloc();
  51. extern void free();
  52.  
  53. int numroll = 1, bestroll = 1;        /* Number of rolls to roll and keep */
  54. int numdice = 1, bestdice = 1;        /* Number of dice to roll and keep */
  55. int sides = 100;            /* Number of sides on each die */
  56.  
  57. int *ar_rolls;                /* Array of rolls */
  58. int *ar_dice;                /* Array of dice */
  59. int *ar_side;                /* Array of side data */
  60.  
  61. char *show();                /* Routine to format output */
  62.  
  63. char iline[80];                /* To parse the roll */
  64. char aroll[80];                /* When rolls are repeated */
  65.  
  66. main(acnt,avar)
  67. int acnt;
  68. char *avar[];
  69. {
  70.     int i, j, k, val;
  71.     char *s, *s1;
  72.  
  73. /*    if(acnt < 2){
  74.     printf("usage: roll {numroll x }{numdice d }{numsides}\n");
  75.     printf("\tExample: roll 100 ; roll 3d8 ; roll 6x3d8\n");
  76.     return;
  77.     }
  78. */
  79.     srandom(time(0L));            /* Randomize */
  80.  
  81.     if(acnt <= 1)            /* Default: Roll 1d100 */
  82.     roll("");
  83.     else
  84.     for(i=0; ++i < acnt;){        /* For each argument */
  85.         s = avar[i];
  86.         if(s1 = index(s,'@')){    /* Repeat the roll? */
  87.         *s1 = 0;
  88.         j = atoi(s);        /* Get repetition */
  89.         if(j < 1){
  90.             printf("roll: Repetition count must be greater than zero.\n");
  91.             return;
  92.             }
  93.         s = s1+1;        /* Advance pointer past it */
  94.         }
  95.         else j = 1;            /* Default: Only one time. */
  96.         strcpy(aroll,s);        /* Save it. */
  97.         while(j--){
  98.         strcpy(s,aroll);
  99.         roll(s);        /* Do the roll */
  100.         }
  101.         }
  102. }
  103.  
  104. roll(inline)
  105. char *inline;
  106. {
  107.     int i, j, k, val, r;
  108.     char *s, *s1;
  109.  
  110.     numroll = bestroll = bestdice = numdice = 1; /* Set defaults. */
  111.     sides = 100;
  112.  
  113.     for(s=inline; *s; ++s)            /* Convert to lower case */
  114.     if(isupper(*s))
  115.         *s = tolower(*s);
  116.  
  117.     s = inline;
  118.     if(s1 = index(s,'x')){            /* Get number of rolls */
  119.     *s1 = 0;
  120.     parse(s,&numroll,&bestroll);
  121.     s = s1+1;
  122.     }
  123.     if(s1 = index(s,'d')){            /* Get number of dice */
  124.     *s1 = 0;
  125.     parse(s,&numdice,&bestdice);
  126.     s = s1+1;
  127.     }
  128.     if(*s) sides = atoi(s);            /* get number of sides */
  129.  
  130.     if(error()) return;                /* Check sanity */
  131.  
  132.     if(numroll > 1) printf("%sx",show(iline,bestroll,numroll));
  133.     if(numdice > 1) printf("%s",show(iline,bestdice,numdice));
  134.     printf("d%d = ",sides);
  135.     fflush(stdout);                /* Echo the command */
  136.  
  137. /* Allocate the arrays - one to keep all the rolls, one to keep each roll
  138.    by the die roll, and one to make sure the dice are rolled RANDOMLY.
  139. */
  140.     ar_rolls = (int *)malloc(sizeof(int) * numroll);
  141.     ar_dice = (int *)malloc(sizeof(int) * numdice);
  142.     ar_side = (int *)malloc(sizeof(int) * NUMREDUX * sides);
  143.  
  144. /* Get out if we couldn't allocate the arrays */
  145.  
  146.     if(!ar_rolls || !ar_dice || !ar_side){
  147.     printf("*** Out of memory ***\n");
  148.     if(ar_rolls) free(ar_rolls);
  149.     if(ar_dice) free(ar_dice);
  150.     if(ar_side) free(ar_side);
  151.     return;
  152.     }
  153.  
  154. /* Make an array filled with the possible side values. Several times. So
  155.    that even if the random number generator isn't completely random, it
  156.    has a chance to produce random values when indexing into the array.
  157. */
  158.     for(i=j=0; i<NUMREDUX; ++i)
  159.     for(k=0; k++ < sides; ++j)
  160.         *(ar_side+j) = k;
  161.  
  162. /* Randomize the array - necessary to catch cyclic random number generators. */
  163.  
  164.     for(i=0; i < NUMREDUX * sides; ++i){
  165.     r = random();
  166.     if(r < 0) r = -r;
  167.     r %= NUMREDUX * sides;
  168.     j = *(ar_side+i);
  169.     *(ar_side+i) = *(ar_side+r);
  170.     *(ar_side+r) = j;
  171.     }
  172.  
  173.     for(i = 0; i<numroll; ++i){            /* For each roll */
  174.     for(j=0; j<numdice; ++j){        /* For each die */
  175.         r = random();            /* Roll the die */
  176.         if(r < 0) r = -r;
  177.         *(ar_dice+j) = *(ar_side + (r % (sides * NUMREDUX)));
  178.         }
  179.     if(bestdice < numdice) sort(ar_dice,numdice); /* Get the best 'n' */
  180.     for(j=val=0; j<bestdice; ++j)        /* Sum them to get the roll */
  181.         val += *(ar_dice+j);
  182.     *(ar_rolls+i) = val;
  183.     }
  184.     sort(ar_rolls,numroll);            /* Sort the rolls */
  185.     for(i=0; i<bestroll; ++i)            /* And print out the best 'n' */
  186.     printf("%d ",*(ar_rolls+i));
  187.     printf("\n");
  188.  
  189.     free(ar_rolls);                /* Free all the arrays */
  190.     free(ar_dice);
  191.     free(ar_side);
  192. }
  193.  
  194. /*****************************************************************************
  195. *    PARSE
  196. *
  197. *    Figure out strings that look like "ddd" and "ddd,ddd", and fill in
  198. *    the values nicely. Handle defaults, too.
  199. ******************************************************************************/
  200.  
  201. parse(s,n,b)
  202. char *s;
  203. int *n, *b;
  204. {
  205.     char *s1;
  206.  
  207.     if(s1 = index(s,',')){
  208.     *s1 = 0;
  209.     *b = atoi(s);
  210.     *n = atoi(s1+1);
  211.     }
  212.     else *b = *n = atoi(s);
  213. }
  214.  
  215. /*****************************************************************************
  216. *    SORT
  217. *
  218. *    Bubble sort (yech) an array.
  219. ******************************************************************************/
  220.  
  221. sort(a,n)
  222. int a[], n;
  223. {
  224.     int changed, i, t;
  225.  
  226.     if(n <= 1) return;
  227.  
  228.     for(changed=1; changed;){
  229.     changed = 0;
  230.     for(i=0; i<n-1; ++i){
  231.         if(a[i] < a[i+1]){
  232.         changed = 1;
  233.         t = a[i]; a[i] = a[i+1]; a[i+1] = t;
  234.         }
  235.         }
  236.     }
  237. }
  238.  
  239. /*****************************************************************************
  240. *    ERROR
  241. *
  242. *    Scan and report any errors.
  243. ******************************************************************************/
  244.  
  245. error(){
  246.     int iserr=0;
  247.  
  248.     if(numroll <= 0){
  249.     fprintf(stderr,"roll: Number of rolls must be greater than zero.\n");
  250.     ++iserr;
  251.     }
  252.  
  253.     if(bestroll < 1 || bestroll > numroll){
  254.     fprintf(stderr,"roll: Number of rolls to keep must be greater than zero,\n");
  255.     fprintf(stderr,"      less than the total number of rolls.\n");
  256.     ++iserr;
  257.     }
  258.  
  259.     if(numdice <= 0){
  260.     fprintf(stderr,"roll: Number of dice to roll must be greater than zero.\n");
  261.     ++iserr;
  262.     }
  263.  
  264.     if(bestdice < 1 || bestdice > numdice){
  265.     fprintf(stderr,"roll: Number of dice to keep must be greater than zero,\n");
  266.     fprintf(stderr,"      less than the number of dice.\n");
  267.     ++iserr;
  268.     }
  269.  
  270.     if(sides <= 1){
  271.     fprintf(stderr,"roll: Dice must have at least two sides.\n");
  272.     ++iserr;
  273.     }
  274.  
  275.     return(iserr);
  276. }
  277.  
  278. /*****************************************************************************
  279. *    SHOW
  280. *
  281. *    Format some output.
  282. ******************************************************************************/
  283.  
  284. char *show(s,b,n)
  285. char *s;
  286. int b, n;
  287. {
  288.     if(b == n)
  289.     sprintf(s,"%d",n);
  290.     else
  291.     sprintf(s,"%d,%d",b,n);
  292.     return(s);
  293. }
  294.