From: kjenks@gothamcity.jsc.nasa.gov
Newsgroups: rec.games.frp.dnd
Subject: jewelry.c (was: gems.c)
Keywords: C program rolling jewelry
Date: 13 Aug 1992 21:35:45 GMT
Organization: NASA/JSC/GM2, Space Shuttle Program Office
Originator: kjenks@krakatoa

I wrote:
>Maybe I'll get jewelry.c done next weakened^H^H^H^H^H^H^H^Hweekend.

Here it is.  I've heard a complaint that the random number generator
misbehaves in Turbo C++ 3.1, but there's probably a work-around.

The output notes which pieces of jewelry have exceptional quality gems
"(nice gems)" or exceptional workmanship "(nice work)."

If you make any modifications, please send them back to me.  Enjoy.

-- Ken Jenks, NASA/JSC/GM2, Space Shuttle Program Office
      kjenks@gothamcity.jsc.nasa.gov  (713) 483-4368

      "Orcs appear particularly disgusting because their
       coloration -- brown or brownish-green with a bluish sheen
       -- highlights their pinkish snouts and ears.  Their
       bristly hair is dark brown or black, sometimes with tan
       patches."
         -- AD&D Monster Manual 1, p. 76.
----------------------------------------------------------------------

/*	AD&D jewelry rolling program,
 *        written August, 1992, by Ken Jenks, 
 *        kjenks@gothamcity.jsc.nasa.gov
 *
 *	This program randomly determines the properties of non-magical
 *      jewelry.
 *
 *	Compile and run with no command line options to see 'usage.'
 */

#include <ctype.h>
#include <math.h>
#include <stdio.h>

static int
bv_table[7][5] = {
 /*  %     n   d     m  g  Jewelry value is n dice of size d, multiplied by m *
  *---    --  --  ----  -  If g = 1, this piece has gems and may increase     */
  { 10,   10, 10,    1, 0},  /* base value place 0 */
  { 20,    2,  6,  100, 0},  /* base value place 1 */
  { 40,    3,  6,  100, 0},  /* base value place 2 */
  { 50,    5,  6,  100, 0},  /* base value place 3 */
  { 70,    1,  6, 1000, 1},  /* base value place 4 */
  { 90,    2,  4, 1000, 1},  /* base value place 5 */
  {100,    2,  6, 1000, 1}}; /* base value place 6 */


static char *
descriptions[7] = {
  "Ivory or wrought silver",          /* 0 */
  "Wrought silver and gold",          /* 1 */
  "Wrought gold",                     /* 2 */
  "Jade, coral or wrought platinum",  /* 3 */
  "Silver with gems",                 /* 4 */
  "Gold with gems",                   /* 5 */
  "Platinum with gems"};              /* 6 */

static char *
kind[51] = {"anklet",
            "arm band",
            "belt",
            "box(small)",
            "bracelet",
            "brooch",
            "buckle",
            "chain",
            "chalice",
            "choker",
            "clasp",
            "collar",
            "comb",
            "coronet",
            "crown",
            "decanter",
            "diadem",
            "earring",
            "fob",
            "goblet",
            "headband(fillet)",
            "idol",
            "locket",
            "medal",
            "medallion",
            "necklace",
            "pendant",
            "pin",
            "orb",
            "ring",
            "sceptre",
            "seal",
            "statuette",
            "tiara",

            "bracers",
            "cup",
            "dagger",
            "flask",
            "helm",
            "horn",
            "mirror",
            "periapt",
            "phylactery",
            "rod",
            "scarab",
            "skull",
            "shield",
            "staff",
            "sword",
            "talisman",
            "trident"};

/************************************************************************
* die_roll() - simple function to roll one die of the given size
************************************************************************/

int die_roll(size)
int size;
{
   return ((rand() % size) + 1);
}

/************************************************************************
* random_jewelry() - randomly determine jewelry
*
************************************************************************/

void
random_jewelry(num_jewelry, base_value, outfile)
int num_jewelry, base_value;
FILE *outfile;
{
  int i;
  long bv, total = 0;
  int bv_die;
  int base_value_place;
  int die;
  int increase_from_gems;
  char * nice_gems;
  char * nice_work;

  fprintf(outfile,"%i piece%s of jewelry, ",
    num_jewelry,
    (num_jewelry!=1)?"s":"");

  if(base_value)
    fprintf(outfile,"base value %i\n\n",base_value);
  else
    fprintf(outfile,"random base values\n\n");

  for (i=1; i<=num_jewelry; i++) {

    if(base_value) {
      bv = base_value;
      /* Calculate base_value_place for later, since no jewelry may *
       * increase more than 7 places beyond its original base value  */
      base_value_place=0;
      while ((base_value_place<12)
        && (base_value > bv_table[base_value_place][1]))
        ++base_value_place;
      if(base_value_place >= 6)
        base_value_place = 5;

    } else {
      bv_die = die_roll(100);
      base_value_place=0;
      while((base_value_place<6)
        && (bv_die >= bv_table[base_value_place][0]))
        base_value_place++;
    }

#ifdef DEBUG
  fprintf(stderr,"\nJewelry #%i\n\n",i);
#endif

    nice_work = "";

roll_bv_dice:

    if(base_value)
      bv = base_value;
    else {
      /* Next, roll the dice and determine bv */
      bv = 0;
      for(bv_die = 1; bv_die <= bv_table[base_value_place][1]; bv_die ++)
        bv += die_roll(bv_table[base_value_place][2]) 
            * bv_table[base_value_place][3];
    }

#ifdef DEBUG
  fprintf(stderr,"  base value: %i\n",bv);
#endif

check_for_exceptional:

#ifdef DEBUG
  fprintf(stderr,"  base value place: %i\n",base_value_place);
#endif

    /* Check for exceptional workmanship */
    if(die_roll(10) == 1) {
      nice_work = " (good work)";

#ifdef DEBUG
  fprintf(stderr,"  Exceptional workmanship: increase from %i\n",bv);
#endif

      if(bv == bv_table[base_value_place][1] * bv_table[base_value_place][2] 
          * bv_table[base_value_place][3])
        if(base_value_place < 6) {
          ++base_value_place;
          goto roll_bv_dice;
        }
        else
          ; /* If already at max, do notthing */
      else {
        /* Set bv to maximum for this base_value_place */
        bv = bv_table[base_value_place][1] * bv_table[base_value_place][2] 
          * bv_table[base_value_place][3];
        goto check_for_exceptional;
      }
    }

    nice_gems = "";
    increase_from_gems = 0;
    if((bv_table[base_value_place][4]) && (die_roll(6) == 1)) {
      increase_from_gems = 5000;
      nice_gems = " (good gems)";
      while((die_roll(6) == 1) && (increase_from_gems <= 200000))
        increase_from_gems = increase_from_gems * 2;
          
#ifdef DEBUG
  fprintf(stderr,"  gems increased value from %i to %i\n",
       bv,bv+increase_from_gems);
#endif
    }

    bv += increase_from_gems;

    fprintf(outfile,"%3i  %7i  (%s) %s%s%s\n",
      i,
      bv, 
      descriptions[base_value_place],
      kind[die_roll(51)-1],
      nice_gems,
      nice_work);

    total += bv;

  } /* end for i */
  fprintf(outfile,"\nTotal: %i\n",total);

}; /* end proc random_jewelry */

main(argc,argv)
int argc;
char **argv;
{
  int num_jewelry;
  int base_value;

  if((argc != 2) && (argc != 3)) {
    fprintf(stderr,"Randomly determines the properties of jewelry.\n");
    fprintf(stderr,"\n");
    fprintf(stderr," usage: %s number [base-value]\n",argv[0]);
    fprintf(stderr,"   where 'number' is the number of pieces of jewelry desired\n");
    fprintf(stderr,"         'base-value' is [optional] base value in GP\n");
    fprintf(stderr,"           (default base-value is random)\n",
             '%','%');
    fprintf(stderr,"\n  Examples: %s 14       (generates 14 pieces of jewelry)\n",
             argv[0]);
    fprintf(stderr,"            %s 12 100   (generates 12 pieces of jewelry, base 100 GPV)\n",argv[0]);
    exit(0);
  }

  num_jewelry = atoi(argv[1]);

  if(argc==3)
    base_value = atoi(argv[2]);
  else
    base_value = 0;

  /* seed random generator, may require system dependant command if
   * time(0) does not work, or might need to use a scanf to get seed */
  srand(time(0));

  random_jewelry(num_jewelry, base_value, stdout);

} /* end main */