/* Rolls up characteristics for D&D character. */

/*#include <time.h>*/
#include <stdlib.h>
#include <graphics.h>

#define MAX 6          /* maximum value for characteristics */
#define TRUE 1
#define FALSE 0

int roll(int);
void display(void);
void pause();
void ability_HCavalier(void);
void ability_HPaladin(void);
void ability_HCleric(void);
void ability_HDruid(void);
void ability_HFighter(void);
void ability_HBarbarian(void);
void ability_HRanger(void);
void ability_HMagicuser(void);
void ability_HIllusionist(void);
void ability_HThief(void);
void ability_HAssassin(void);
void ability_HMonk(void);
void main(void);

char *page1 = {
"\n"
"Ability scores were generated according to Method V. in the 'Official Advanced\n"
"Dungeons & Dragons Unearthed Arcana' book by Gary Gygax on page 74.\n"
"\n"
"These ability scores are for human player characters and should be subject to\n"
"approval by your Dungeon Master.\n"
"\n"
"             Class         Number of 1d6's rolled for each:\n"
"             Desired       Str  Int  Wis  Dex  Con  Cha  Com\n"
"             ------------------------------------------------\n"
"             Calvalier      8    6    4    7    9    3    5\n"
"              Paladin       7    5    8    3    6    9    4\n"
"             Cleric         7    4    9    5    8    6    3\n"
"              Druid         7    4    8    5    6    9    3\n"
"             Fighter        9    3    5    7    8    6    4\n"
"              Barbarian     9    3    5    7    8    6    4\n"
"              Ranger        7    6    8    5    9    4    3\n"
"             Magic-User     4    9    7    8    6    5    3\n"
"              Illusionist   3    8    7    9    5    6    4\n"
"             Thief          6    5    3    9    7    4    8\n"
"              Assassin      6    7    4    9    8    3    5\n"
"             Monk           7    5    9    8    6    4    3\n"
};

char *page2 = {
"\n"
" Note: Only the highest 3 dice rolled are used for an ability score.\n"
"\n"
"       Also ability scores do not take into account min. or max. scores\n"
"       allowed for each character type. You will have to refer to your,\n"
"       'Official Advanced Dungeon & Dragons Players Handbook' by Gary\n"
"       Gygax for that information.\n"
"\n"
" Advanced Dungeons & Dragons and AD&D are trademarks owned by TSR Hobbies, Inc."
"\n"
"\n"
"  Please fill free to improve this program or use any part of its source. I\n"
"  would appreicate hearing your comments, suggestions, or seeing how you have\n"
"  improved on this program."
"\n"
"\n"
"  My name is Dale Klipstein and you can contact me on most any IBM BBS in\n"
"  Milwaukee, Wis."
};


int roll(int numb_rolls)
{
 int x = MAX + 1;
 int result = 0;
 int i,n,arow,brow,dist,temp,temp2;
 int total[10];                      /*9 is the max rolls*/

 for (i = 1; i <= 9; i++)
   total[i] = 0;


 for (i = 1; i <= numb_rolls; i++)   /*roll 6 sided dice (x) times*/
   {
    do {
        result = random(x);          /*roll a die*/
       } while(result == 0);         /*make sure its nots a zero*/

    total[i] = result;          /*add up all the rolls of the die*/
   }

  /*shell metzner sort routine to single out the top 3 highest rolls*/

   n = numb_rolls;

   dist = n;

   loop:
   dist = dist/2;

   for (arow = 1; arow <= (n-dist); arow++)
      {
       brow = arow + dist;
       if (total[arow] > total[brow])
         {
          temp        = total[arow];    /*swap data*/
          total[arow] = total[brow];
          total[brow] = temp;

          temp2 = arow;

          loop2:
          if (temp2 > dist)
            if (total[temp2-dist] > total[temp2])
              {
               temp                = total[temp2 - dist];  /*swap data*/
               total[temp2 - dist] = total[temp2];
               total[temp2]        = temp;

               temp2 = temp2 - dist;

               goto loop2;
              }

         }
      }
 if (dist > 1)
     goto loop;

 /*total only the top 3 highest rolls*/
 result = total[numb_rolls] + total[numb_rolls-1] + total[numb_rolls-2];

 return(result);
}

void display(void)
{
 int i;

 gotoxy(2,2);
 cprintf("Cavalier");
 gotoxy(16,2);
 cprintf("Paladin");
 gotoxy(30,2);
 cprintf("Cleric");
 gotoxy(44,2);
 cprintf("Druid");
 gotoxy(58,2);
 cprintf("Fighter");
 gotoxy(72,2);
 cprintf("Barbarian");
 gotoxy(2,12);
 cprintf("Ranger");
 gotoxy(16,12);
 cprintf("Magic-user");
 gotoxy(30,12);
 cprintf("Illusionist");
 gotoxy(44,12);
 cprintf("Thief");
 gotoxy(58,12);
 cprintf("Assassin");
 gotoxy(72,12);
 cprintf("Monk");

 for (i=2; i <= 79; i = i+14)
   {
    gotoxy(i,4);
    cprintf("STR =   ");
    gotoxy(i,5);
    cprintf("INT =   ");
    gotoxy(i,6);
    cprintf("WIS =   ");
    gotoxy(i,7);
    cprintf("DEX =   ");
    gotoxy(i,8);
    cprintf("CON =   ");
    gotoxy(i,9);
    cprintf("CHA =   ");
    gotoxy(i,10);
    cprintf("COM =   ");
    gotoxy(i,14);
    cprintf("STR =   ");
    gotoxy(i,15);
    cprintf("INT =   ");
    gotoxy(i,16);
    cprintf("WIS =   ");
    gotoxy(i,17);
    cprintf("DEX =   ");
    gotoxy(i,18);
    cprintf("CON =   ");
    gotoxy(i,19);
    cprintf("CHA =   ");
    gotoxy(i,20);
    cprintf("COM =   ");
   }
}

void ability_HCavalier(void)
{
 gotoxy(8,4);
 cprintf("%d ", roll(8));   /* STR */
 gotoxy(8,5);
 cprintf("%d ", roll(6));   /* INT */
 gotoxy(8,6);
 cprintf("%d ", roll(4));   /* WIS */
 gotoxy(8,7);
 cprintf("%d ", roll(7));   /* DEX */
 gotoxy(8,8);
 cprintf("%d ", roll(9));   /* CON */
 gotoxy(8,9);
 cprintf("%d ", roll(3));   /* CHA */
 gotoxy(8,10);
 cprintf("%d ", roll(5));   /* COM */
}

void ability_HPaladin(void)
{
 gotoxy(22,4);
 cprintf("%d ", roll(7));   /* STR */
 gotoxy(22,5);
 cprintf("%d ", roll(5));   /* INT */
 gotoxy(22,6);
 cprintf("%d ", roll(8));   /* WIS */
 gotoxy(22,7);
 cprintf("%d ", roll(3));   /* DEX */
 gotoxy(22,8);
 cprintf("%d ", roll(6));   /* CON */
 gotoxy(22,9);
 cprintf("%d ", roll(9));   /* CHA */
 gotoxy(22,10);
 cprintf("%d ", roll(4));   /* COM */
}

void ability_HCleric(void)
{
 gotoxy(36,4);
 cprintf("%d ", roll(7));   /* STR */
 gotoxy(36,5);
 cprintf("%d ", roll(4));   /* INT */
 gotoxy(36,6);
 cprintf("%d ", roll(9));   /* WIS */
 gotoxy(36,7);
 cprintf("%d ", roll(5));   /* DEX */
 gotoxy(36,8);
 cprintf("%d ", roll(8));   /* CON */
 gotoxy(36,9);
 cprintf("%d ", roll(6));   /* CHA */
 gotoxy(36,10);
 cprintf("%d ", roll(3));   /* COM */
}

void ability_HDruid(void)
{
 gotoxy(50,4);
 cprintf("%d ", roll(7));   /* STR */
 gotoxy(50,5);
 cprintf("%d ", roll(4));   /* INT */
 gotoxy(50,6);
 cprintf("%d ", roll(8));   /* WIS */
 gotoxy(50,7);
 cprintf("%d ", roll(5));   /* DEX */
 gotoxy(50,8);
 cprintf("%d ", roll(6));   /* CON */
 gotoxy(50,9);
 cprintf("%d ", roll(9));   /* CHA */
 gotoxy(50,10);
 cprintf("%d ", roll(3));   /* COM */
}

void ability_HFighter(void)
{
 gotoxy(64,4);
 cprintf("%d ", roll(9));   /* STR */
 gotoxy(64,5);
 cprintf("%d ", roll(3));   /* INT */
 gotoxy(64,6);
 cprintf("%d ", roll(5));   /* WIS */
 gotoxy(64,7);
 cprintf("%d ", roll(7));   /* DEX */
 gotoxy(64,8);
 cprintf("%d ", roll(8));   /* CON */
 gotoxy(64,9);
 cprintf("%d ", roll(6));   /* CHA */
 gotoxy(64,10);
 cprintf("%d ", roll(4));   /* COM */
}

void ability_HBarbarian(void)
{
 gotoxy(78,4);
 cprintf("%d ", roll(9));   /* STR */
 gotoxy(78,5);
 cprintf("%d ", roll(3));   /* INT */
 gotoxy(78,6);
 cprintf("%d ", roll(5));   /* WIS */
 gotoxy(78,7);
 cprintf("%d ", roll(7));   /* DEX */
 gotoxy(78,8);
 cprintf("%d ", roll(8));   /* CON */
 gotoxy(78,9);
 cprintf("%d ", roll(6));   /* CHA */
 gotoxy(78,10);
 cprintf("%d ", roll(4));   /* COM */
}

void ability_HRanger(void)
{
 gotoxy(8,14);
 cprintf("%d ", roll(7));   /* STR */
 gotoxy(8,15);
 cprintf("%d ", roll(6));   /* INT */
 gotoxy(8,16);
 cprintf("%d ", roll(8));   /* WIS */
 gotoxy(8,17);
 cprintf("%d ", roll(5));   /* DEX */
 gotoxy(8,18);
 cprintf("%d ", roll(9));   /* CON */
 gotoxy(8,19);
 cprintf("%d ", roll(4));   /* CHA */
 gotoxy(8,20);
 cprintf("%d ", roll(3));   /* COM */
}

void ability_HMagicuser(void)
{
 gotoxy(22,14);
 cprintf("%d ", roll(4));   /* STR */
 gotoxy(22,15);
 cprintf("%d ", roll(9));   /* INT */
 gotoxy(22,16);
 cprintf("%d ", roll(7));   /* WIS */
 gotoxy(22,17);
 cprintf("%d ", roll(8));   /* DEX */
 gotoxy(22,18);
 cprintf("%d ", roll(6));   /* CON */
 gotoxy(22,19);
 cprintf("%d ", roll(5));   /* CHA */
 gotoxy(22,20);
 cprintf("%d ", roll(3));   /* COM */
}

void ability_HIllusionist(void)
{
 gotoxy(36,14);
 cprintf("%d ", roll(3));   /* STR */
 gotoxy(36,15);
 cprintf("%d ", roll(8));   /* INT */
 gotoxy(36,16);
 cprintf("%d ", roll(7));   /* WIS */
 gotoxy(36,17);
 cprintf("%d ", roll(9));   /* DEX */
 gotoxy(36,18);
 cprintf("%d ", roll(5));   /* CON */
 gotoxy(36,19);
 cprintf("%d ", roll(6));   /* CHA */
 gotoxy(36,20);
 cprintf("%d ", roll(4));   /* COM */
}

void ability_HThief(void)
{
 gotoxy(50,14);
 cprintf("%d ", roll(6));   /* STR */
 gotoxy(50,15);
 cprintf("%d ", roll(5));   /* INT */
 gotoxy(50,16);
 cprintf("%d ", roll(3));   /* WIS */
 gotoxy(50,17);
 cprintf("%d ", roll(9));   /* DEX */
 gotoxy(50,18);
 cprintf("%d ", roll(7));   /* CON */
 gotoxy(50,19);
 cprintf("%d ", roll(4));   /* CHA */
 gotoxy(50,20);
 cprintf("%d ", roll(8));   /* COM */
}

void ability_HAssassin(void)
{
 gotoxy(64,14);
 cprintf("%d ", roll(6));   /* STR */
 gotoxy(64,15);
 cprintf("%d ", roll(7));   /* INT */
 gotoxy(64,16);
 cprintf("%d ", roll(4));   /* WIS */
 gotoxy(64,17);
 cprintf("%d ", roll(9));   /* DEX */
 gotoxy(64,18);
 cprintf("%d ", roll(8));   /* CON */
 gotoxy(64,19);
 cprintf("%d ", roll(3));   /* CHA */
 gotoxy(64,20);
 cprintf("%d ", roll(5));   /* COM */
}

void ability_HMonk(void)
{
 gotoxy(78,14);
 cprintf("%d ", roll(7));   /* STR */
 gotoxy(78,15);
 cprintf("%d ", roll(5));   /* INT */
 gotoxy(78,16);
 cprintf("%d ", roll(9));   /* WIS */
 gotoxy(78,17);
 cprintf("%d ", roll(8));   /* DEX */
 gotoxy(78,18);
 cprintf("%d ", roll(6));   /* CON */
 gotoxy(78,19);
 cprintf("%d ", roll(4));   /* CHA */
 gotoxy(78,20);
 cprintf("%d ", roll(3));   /* COM */
}

void preinfo(void)
{
 window(1,25,80,25);
 textcolor(YELLOW);
 textbackground(BLUE);
 clrscr();
 gotoxy(29,1);
 cprintf("Press space bar to continue.");

 window(1,2,80,24);
 textcolor(YELLOW);
 textbackground(BLACK);

 clrscr();
 cprintf("%s",page1);
 pause();

 clrscr();
 cprintf("%s",page2);
 pause();
}

void pause(void)
{
 char ch,test = TRUE;

 while(test)
  {
   if (kbhit())
     ch = getch();
   if (ch == 32)
     test = FALSE;
  }
}



void main(void)
{
 char ch, test = TRUE;

 randomize();

 window(1,1,80,1);
 textcolor(YELLOW);
 textbackground(BLUE);
 clrscr();
 gotoxy(21,1);
 cprintf("AD & D ABILITY SCORES GENERATOR V1.00");

 preinfo();

 window(1,25,80,25);
 textcolor(YELLOW);
 textbackground(BLUE);
 clrscr();
 gotoxy(22,1);
 cprintf("Any key to roll again.  'Q' to Quit");

 window(1,2,80,24);
 textcolor(YELLOW);
 textbackground(BLACK);
 clrscr();
 display();
 while(test)
  {
   /*clear_numbs();*/
   ability_HCavalier();
   ability_HPaladin();
   ability_HCleric();
   ability_HDruid();
   ability_HFighter();
   ability_HBarbarian();
   ability_HRanger();
   ability_HMagicuser();
   ability_HIllusionist();
   ability_HThief();
   ability_HAssassin();
   ability_HMonk();
   while(TRUE)
     {
     if (kbhit());
       {
       ch = toupper(getch());
       if (ch == 'Q')
         test = FALSE;
       break;
       }
     }
  }
}
