[alt.sources] Rolemaster FRP NPC stat-generating program

lee@sq.sq.com (Liam R. E. Quin) (09/04/90)

I wrote this program several years ago when I first started running rolemaster.
It doesn't compile on our sun4 (the C compiler chokes) but it works fine on a
Sun3 and under Saber-C (which helped me fix some five-year-old bugs).

Sample output:

Name: Vartayn
Class: Magician
Stat	Pot	Temp	Mod
Str	93	93	10
Qu	81	81	5
Pr	90	48	0
In	78	21	-5
Em	94	94	10
Co	95	92	10
Ag	76	46	0
SD	38	24	-5
Me	98	98	20
Re	85	72	0

If this means nothing to you, you probably don't want it!
There is some ifdef'd code for generating lists of skills, but it looks to
me as if it was barely started and doesn't work.
A more useful program would generate notes on the peoples' personalities...

The random names are generated by opening in pipe to "names -i", which
generates an "infinite" stream of random names.

I am not sure I like this coding style very much.  I don't use it now...
But it's free :-)

Just do
	cc -o npc npc.c

It takes a single optional argument, the number of people to make.


The stat selection algorithm is table driven -- it chooses the most suitable
class for a character given its stats.  It uses the PC rules for rerolling
stats less than 20.  You can chenge this table -- see the end of tables.h --
the stats are multiplied by the weights given in the table, and the highest
result is used.  You could outlaw strong bards, for example, by making the
first number in the last column of ClassStatWeightingTable[] be -10000, or
make strong bards less likely by setting it to -0.1 if you wanted.
Suggestions for improvements [not involving the "rm" utility :-)] welcomed.

If you don't have a random names program, I could post the ones I have.


Lee


: To unbundle, sh this file
echo x - npc.c 1>&2
sed 's/^X//' >npc.c <<'@@@End of npc.c'
X/******************************************************************************
X*
X* chargen -- generate Rolemaster characters
X*
X* Liam Quin, 1990 (from an earlier version written in 1985 or so)
X*
X*******************************************************************************/
X
X#include <stdio.h>
X
X#define NAMEPIPE "names -i"
X
X#define etoiskill(e) ((int) e)
X
X#ifndef lint
X static char *Revision = "@(#) $Header: /home/lee/russ1/req/frp/rolemaster/src/npc.c,v 1.2 90/09/03 21:53:38 lee Exp $";
X /* This is to enable what(1) to identify the program */
X#endif
X
X#define RANDPRIME 37	/* divide rand() by this */
X
X
X#define NumberOfStats	10
Xtypedef int t_statarray[NumberOfStats];
X
Xtypedef enum {
X     StatStr, StatQu, StatPr, StatIn, StatEm,
X     StatCo,  StatAg, StatSD, StatMe, StatRe,
X     NoSuchStat	/* catchall! */
X} te_stat;
X
X#define is_development_stat(x)	( (x) <= StatEm )
X
Xetoistat(stat)
X     te_stat stat;
X{
X     switch (stat) {
X	  case StatStr:	return 0;
X	  case StatQu:	return 1;
X	  case StatPr:	return 2;
X	  case StatIn:	return 3;
X	  case StatEm:	return 4;
X	  case StatCo:	return 5;
X	  case StatAg:	return 6;
X	  case StatSD:	return 7;
X	  case StatMe:	return 8;
X	  case StatRe:	return 9;
X	  default: 	return -1;
X     }
X}
X
Xte_stat
Xitoestat(i)
X     int i;
X{
X     switch (i) {
X	  case 0:	return	StatStr;
X	  case 1:	return	StatQu;
X	  case 2:	return	StatPr;
X	  case 3:	return	StatIn;
X	  case 4:	return	StatEm;
X	  case 5:	return	StatCo;
X	  case 6:	return	StatAg;
X	  case 7:	return	StatSD;
X	  case 8:	return	StatMe;
X	  case 9:	return	StatRe;
X	  default: 	return  NoSuchStat;
X     }
X}
X
X
Xchar *
Xetosstat(stat)
X     te_stat stat;
X{
X     switch (stat) {
X	  case StatStr:	return "Str" ;
X	  case StatQu:	return "Qu" ;
X	  case StatPr:	return "Pr" ;
X	  case StatIn:	return "In" ;
X	  case StatEm:	return "Em" ;
X	  case StatCo:	return "Co" ;
X	  case StatAg:	return "Ag" ;
X	  case StatSD:	return "SD" ;
X	  case StatMe:	return "Me" ;
X	  case StatRe:	return "Re" ;
X	  default: 	return "Unknown stat type" ;
X     }
X}
X
X
Xtypedef enum {
X     ClassFighter,	ClassThief,		ClassRogue,
X     ClassWarriorMonk,
X     ClassMagician,	ClassIllusionist,	ClassAlchemist,
X     ClassCleric,	ClassAnimist,		ClassHealer,
X     ClassMentalist,	ClassLayHealer,		ClassSeer,
X     ClassSorceror,	ClassMystic,		ClassAstrologer,
X     ClassMonk,		ClassRanger,		ClassBard
X} te_cclass;
X
X#define MAXCCLASSLENGTH 12 /* length of the longest enum, excluding a null */
X#define NumberOfCClasses 19
X
Xchar *
Xetoscclass(class)
X     te_cclass class;
X{
X     switch(class) {
X	  case ClassFighter:		return "Fighter";
X	  case ClassThief:		return "Thief";
X	  case ClassRogue:		return "Rogue";
X	  case ClassWarriorMonk:	return "Warrior Monk";
X	  case ClassMagician:		return "Magician";
X	  case ClassIllusionist:	return "Illusionist";
X	  case ClassAlchemist:		return "Alchemist";
X	  case ClassCleric:		return "Cleric";
X	  case ClassAnimist:		return "Animist";
X	  case ClassHealer:		return "Healer";
X	  case ClassMentalist:		return "Mentalist";
X	  case ClassLayHealer:		return "Lay Healer";
X	  case ClassSeer:		return "Seer";
X	  case ClassSorceror:		return "Sorceror";
X	  case ClassMystic:		return "Mystic";
X	  case ClassAstrologer:		return "Astrologer";
X	  case ClassMonk:		return "Monk";
X	  case ClassRanger:		return "Ranger";
X	  case ClassBard:		return "Bard";
X	  default:			return "Unknown Profession";
X     }
X}
X
Xtypedef enum {
X     SkillSoftLeather, SkillRigidLeather, SkillChain, SkillPlate,
X
X     SkillWeapon1, SkillWeapon2, SkillWeapon3,
X     SkillWeapon4, SkillWeapon5, SkillWeapon6,
X
X     SkillClimbing, SkillSwimming, SkillRiding, SkillDisarmTraps,
X     SkillPickLocks, SkillStalkandHide, SkillPerception,
X
X     SkillSpellLists, SkillRunes, SkillStavesAndWands,
X     SkillChanneling, SkillDirectedSpells,
X
X     SkillAmbush, SkillLinguistics, SkillAdrenalMoves,
X     SkillAdrenalDefense, SkillMartialArts, SkillBodyDevelopment
X} te_skill;
X
X#define NumberOfSkills 28
X
Xchar *
Xetosskill(skill)
X     te_skill skill;
X{
X     switch (skill) {
X	  case SkillSoftLeather:	return "Soft Leather";
X	  case SkillRigidLeather:	return "Rigid Leather";
X	  case SkillChain:		return "Chain";
X	  case SkillPlate:		return "Plate";
X	  case SkillWeapon1:		return "Weapon 1";
X	  case SkillWeapon2:		return "Weapon 2";
X	  case SkillWeapon3:		return "Weapon 3";
X	  case SkillWeapon4:		return "Weapon 4";
X	  case SkillWeapon5:		return "Weapon 5";
X	  case SkillWeapon6:		return "Weapon 6";
X	  case SkillClimbing:		return "Climbing";
X	  case SkillSwimming:		return "Swimming";
X	  case SkillRiding:		return "Riding";
X	  case SkillDisarmTraps:	return "Disarm Traps";
X	  case SkillPickLocks:		return "Pick Locks";
X	  case SkillStalkandHide:	return "Stalking and Hiding";
X	  case SkillPerception:		return "Perception";
X	  case SkillSpellLists:		return "Spell Lists";
X	  case SkillRunes:		return "Runes";
X	  case SkillStavesAndWands:	return "Staves And Wands";
X	  case SkillChanneling:		return "Channeling";
X	  case SkillDirectedSpells:	return "Directed Spells";
X	  case SkillAmbush:		return "Ambush";
X	  case SkillLinguistics:	return "Linguistics";
X	  case SkillAdrenalMoves:	return "Adrenal Moves";
X	  case SkillAdrenalDefense:	return "Adrenal Defense";
X	  case SkillMartialArts:	return "Martial Arts";
X	  case SkillBodyDevelopment:	return "Body Development";
X	  default:			return "No Such Skill!";
X     }
X}
X
Xtypedef enum { BonusStat, BonusDP, BonusPP } te_bonustype;
X
Xchar *
Xetosbonustype(t)
X     te_bonustype t;
X{
X     switch(t) {
X	  case BonusStat:	return "Stat" ;
X	  case BonusDP:		return "DP"   ;
X	  case BonusPP:		return "PP"   ;
X	  default:		return "Unknown bonus type";
X     }
X}
X
X
Xtypedef struct {
X     int  firstcost,	/* DP cost for 1 skill level */
X	  secondcost;	/* DP cost for next; -ve if any amount allowed. */
X} ts_skillcostpair;
X
Xtypedef struct {
X     char *skillname;
X     te_skill whichskill;
X     int  level,	/* expertise in this skill (in LEVELS) */
X	  totalslashes;	/* how many LEVELS we go up at the next oppertunity */
X     ts_skillcostpair cost;
X} t_skillslist;
X
X
Xtypedef struct {
X     te_cclass whom;
X     ts_skillcostpair skills[NumberOfSkills];
X} t_skilltable[ NumberOfCClasses ];
X
Xtypedef struct {
X     t_statarray stats;
X     t_statarray potentials;
X     t_statarray mods;
X     te_cclass cclass;
X     t_skillslist skills[(int) SkillBodyDevelopment + 1];
X     int hitpoints;
X     int powerpoints,
X	 developmentpoints;
X     char *name;
X     int level;
X} t_person;
X
X#include "tables.h"
X
Xmain(argc, argv)
X     int argc;
X     char *argv[];
X{
X     int count = 0;
X     int crowdsize = 1;
X     int leveltobe = 1;
X     t_person hitpoints(), statpotentials(), chooseprofession(), rollstats();
X     char *choosename();
X
X     if (argc > 1)
X	  crowdsize = atoi(argv[1]);
X
X     srand(getpid());
X
X     while (count++ < crowdsize) {
X#ifdef DOSKILLS
X	  int training = 0;
X#endif
X	  t_person thisbod;
X
X	  thisbod.hitpoints = 0;
X	  thisbod = hitpoints(statpotentials(chooseprofession(rollstats(thisbod))));
X#if DOSKILLS
X	  do {
X	       chooseskills(thisbod);
X	       skillsandbonuses(thisbod);
X	  } while (training++ < leveltobe);
X	  chooseskills(thisbod);
X#endif
X	  thisbod.name = choosename(thisbod);
X	  printcharsheet(thisbod);
X     }
X}
X
Xt_person
Xrollstats(bod)
X     t_person bod;
X{
X     int i = 0;
X
X     for (i = 0; i < NumberOfStats; i++) {
X	  /* ignore throws less than 20 for attributes...
X	   * actually this is probably a mistake for an npc...
X	   */
X	  while ((bod.stats[i] = d(100)) < 20)
X	       ;
X     }
X     return bod;
X}
X
Xt_person
Xchooseprofession(thisfellow)
X     t_person thisfellow;
X{
X     double weight[ NumberOfCClasses ];
X     int maxweight = 0;
X     int i, j;
X
X     for (i = 0; i < NumberOfCClasses; i++) {
X	  weight[i] = 0.0;
X
X	  for (j = 0; j < NumberOfStats; j++) {
X	       weight[i] += ClassStatWeightingTable[i].weightings[j] * thisfellow.stats[j];
X	  }
X	  if (weight[i] > weight[maxweight]) {	/* "best so far" */
X	       maxweight = i;
X	  }
X     }
X
X     thisfellow.cclass = ClassStatWeightingTable[maxweight].cclass;
X     return thisfellow;
X}
X
Xt_person
Xstatpotentials(bod)
X     t_person bod;
X{
X     int i = 0;
X
X     bod.powerpoints = bod.developmentpoints = 0;
X     for (i = 0; i < NumberOfStats; i++) {
X	  bod.potentials[i] = RollOnStatPotentialTable(bod.stats[i], d(100));
X	  bod.mods[i] = ConsultBonusTable(bod.stats[i], BonusStat);
X	  if (etoistat(StatEm) >= i) { /* should use is_development_stat */
X	       bod.developmentpoints += ConsultBonusTable(bod.stats[i], BonusDP);
X	  }
X     }
X     return bod;
X}
X
XRollOnStatPotentialTable(originalstat, n)
X     int originalstat, n;
X{
X     int x = StatPotentialTable[maptable15p11[n-1]][map15p11(originalstat-1)];
X     return (x <= 0) ? originalstat : x;
X}
X
XConsultBonusTable(statroll, reason)
X     int statroll;
X     te_bonustype reason;
X{
X     int row;
X     int col;
X
X     switch (reason) {
X	  case BonusStat:	col = 0; break;
X	  case BonusDP:		col = 1; break;
X	  case BonusPP:		col = 2; break;
X	  default: /* can't happen :-) */
X	       error(__LINE__, __FILE__, "reason = %d\n", (int) reason);
X	       abort();
X     }
X
X     if (statroll == 1) row = 0;
X     else if (statroll == 2) row = 1;
X     else if (statroll <= 4) row = 2;
X     else if (statroll <= 9) row = 3;
X     else if (statroll <= 14) row = 4;
X     else if (statroll <= 24) row = 5;
X     else if (statroll <= 39) row = 6;
X     else if (statroll <= 59) row = 7;
X     else if (statroll <= 74) row = 8;
X     else if (statroll <= 84) row = 9;
X     else if (statroll <= 89) row = 10;
X     else if (statroll <= 94) row = 11;
X     else if (statroll <= 97) row = 12;
X     else if (statroll <= 99) row = 13;
X     else if (statroll <= 100) row = 14;
X     else if (statroll <= 101) row = 15;
X     else if (statroll <= 102) row = 16;
X     else row = 17;
X
X     return StatBonusTable[row][col];
X}
X
Xd(n)
X     int n;
X{
X     return ( ( rand() / RANDPRIME ) % n ) + 1;
X}
X
Xt_person
Xhitpoints(bod)
X     t_person bod;
X{
X     bod.hitpoints += d(10);
X     return bod;
X}
X
Xmap15p11(stat)
X     int stat;
X{
X     if (stat < 25) return 0;
X     else if (stat < 40) return 1;
X     else if (stat < 60) return 2;
X     else if (stat < 75) return 3;
X     else if (stat < 85) return 4;
X     else if (stat < 90) return 5;
X     else if (stat < 95) return 6;
X     else if (stat < 98) return 7;
X     else if (stat < 100) return 8;
X     else return 9;
X}
X
X/* print the fellow out...
X */
X
Xprintcharsheet(bod)
X     t_person bod;
X{
X     int i = 0;
X
X     printf("Name: %s\nClass: %s\n",
X		(bod.name && bod.name[0]) ? bod.name : "Rasputin",
X		etoscclass(bod.cclass));
X     puts("Stat\tPot\tTemp\tMod");
X     for (i = 0; i < NumberOfStats; i++) {
X	  printf("%s\t%d\t%d\t%d\n",    etosstat( (te_stat) i),
X					bod.potentials[i],
X					bod.stats[i],
X					bod.mods[i]);
X     }
X     printskills(bod);
X     puts("\n\n");
X}
X
X#ifdef DOSKILLS
X
Xchooseskills(bod)
X     t_person bod;
X{
X
X     /* build a list of skills that are available to us			*/
X     /* and then choose the best selection therefrom			*/
X     /* Finally, add the skills to the ones that the bod already have	*/
X     /* but we don't get the benefits yet.... */
X
X     addpendingskills(bod, makeselection(bod, buildlistofskills(bod)));
X}
X
X#endif
X
X
Xprintskills(bod)
X     t_person bod;
X{
X     int i;
X
X     for (i = 0; i <= etoiskill(SkillBodyDevelopment); i++) {
X	  if (bod.skills[i].level > 0) {
X	       printf("%d\t%s\n", bod.skills[i], etosskill(i));
X	  }
X     }
X}
X
X
X#ifdef DOSKILLS
Xskillsandbonuses(bod)
X     t_person bod;
X{
X     chooseskills(bod);
X     benefitsforskills(bod);
X     skillbonuses(bod);
X}
X
Xlist *
Xbuildlistofskills(bod)
X     t_person bod;
X{
X      static skill_n firstval;
X
X     /* here we have to make a list of all the skill selections that bod could
X      * make, together with a `desireability rating' GAIN for each.
X      */
X      firstval.next = NULL;
X      firstval.gain = 2.0;	/* too big so it stays at the front... */
X      for (skill_n = 0; skill_n <= (int) SkillBodyDevelopment; skill_n++) {
X      /* do multiple selections here. NOTDONE */
X	  list *this = (skill *) malloc(sizeof(skill));
X	  list *p;	/* for list-marching later... */
X
X	  this->oldlevel = bod.skills[skill_n];
X	  this->newlevel = this->oldlevel[skill_n];
X	  this->which = skill_n;
X	  this->gain = desireability(bod,this);
X	  this->next = NULL;
X	  for (p = &firstval; p->next != NULL; p = p->next) {
X	       if (p->gain < this->gain ||
X				   (p-gain == this->gain && rand() % 2)) {
X		    break;
X	       }
X	  }
X	  if (p->next == NULL) {
X	       /* end of the list */
X	       p->next = this;
X	  } else {
X	       this->next = p->next;
X	       p->next = this;
X	  }
X     }
X     return firstval.next;
X}
X#endif /* DOSKILLS */
X
Xchar *
Xchoosename(bod)
X     t_person bod;
X{
X     /* choose a suitable name... */
X     static FILE *NamePipe = 0;
X     static char Result[100];
X
X     if (!NamePipe) {
X	  if ((NamePipe = popen(NAMEPIPE, "r")) == (FILE *) 0) {
X	       error(__LINE__, __FILE__, "can't open pipe %s\n", NAMEPIPE);
X	       exit(1);
X	  }
X     }
X
X     return fgets(Result, sizeof(Result) - 1, NamePipe);
X}
X
X
X#ifdef DOSKILLS
X
XstratagyP(l, dp, q)
X     list *l, *q;
X     int dp;
X{
X     in v, v1;
X     list *q1 = NULL, *q2 = NULL, *p = l;
X
X     while (p && p->cost > dp)
X	  p = p->next;
X
X     if (p == NULL)
X	  return 0;
X
X     if (p->next == NULL) {
X	  append1(q, p);
X	  return p->gain;
X     }
X
X     v1 = p->gain + strategyP(p->next, dp - p->cost, q1);	/* buy p */
X     v2 = strategyP(p->next, dp, q2);	/* or pass it by... ? */
X
X     if (v1 > v2) {
X	  /* so it's a good idea to but p */
X	  append1(q, p);
X	  append(q, q1);
X	  return v1;
X     } else {
X	  append(q, q1);
X	  return v2;
X     }
X}
X
Xappend1(l1, l2)
X     list *l1, *l2;
X{
X     register list *ptr = l1;
X     list *p = new(list);
X
X     *p = l2;
X     p->next = NULL;
X     while (l1 && l1->next)
X	  l1 = l1->next;
X     if (l1 == NULL)
X	  return -1;
X     l1->next = p;
X}
X
X
Xappend(l1, l2)
X     list *l1, *l2;
X{
X     register list *ptr = l1;
X
X     p->next = NULL;
X     while (l1 && l1->next)
X	  l1 = l1->next;
X     if (l1 == NULL)
X	  return -1;
X     l1->next = l2;
X}
X
X#endif
X
X
Xerror(file, line, msg, a, b, c)
X     char *file;
X     int line;
X     char *msg;
X{
X     fprintf(stderr, "%s:%d:", file, line);
X     fprintf(stderr, msg, a, b, c);
X}
X
X/* $Log:	npc.c,v $
X * Revision 1.2  90/09/03  21:53:38  lee
X * Fixed some typos and an out-by-one error in maptable lookup.
X * Added input pipe to random names program.
X * 
X * Revision 1.1  90/09/03  21:16:25  lee
X * Initial revision
X * 
X *
X */
@@@End of npc.c
echo x - tables.h 1>&2
sed 's/^X//' >tables.h <<'@@@End of tables.h'
X/* maptable for 15.11 -- given the d100 roll, which row of the stat potential
X * table should we use?
X */
Xint maptable15p11[] = {
X/* 01-10 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X/* 11-20 */	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
X/* 21-30 */	2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X/* 31-35 */	3, 3, 3, 3, 3,
X/* 36-40 */	4, 4, 4, 4, 4,
X/* 41-45 */	5, 5, 5, 5, 5,
X/* 46-49 */	6, 6, 6, 6,
X/* 50-51 */	7, 7,
X/* 52-53 */	8, 8,
X/* 54-55 */	9, 9,
X/* 56-57 */	10, 10,
X/* 58-59 */	11, 11,
X/* 60-61 */	12, 12,
X/* 62-63 */	13, 13,
X/* 64-65 */	14, 14,
X/* 66-67 */	15, 15,
X/* 68-69 */	16, 16,
X/* 70-71 */	17, 17,
X/* 72-73 */	18, 18,
X/* 74-75 */	19, 19,
X/* 76-77 */	20, 20,
X/* 78-79 */	21, 21,
X/* 80-81 */	22, 22,
X/* 82-83 */	23, 23,
X/* 84-85 */	24, 24,
X/* 86-87 */	25, 25,
X/* 88-89 */	26, 26,
X/* 90 */	27,
X/* 91 */	28,
X/* 92 */	29,
X/* 93 */	30,
X/* 94 */	31,
X/* 95 */	32,
X/* 96 */	33,
X/* 97 */	34,
X/* 98 */	35,
X/* 99 */	36,
X/* 100 */	37,
X/* oops! */	-1
X};
X
X/* table 15.11 */
Xint StatPotentialTable[][10] = {
X/* 01-10 */	{ 25, 0, },
X/* 11-20 */	{ 30, 0, },
X/* 21-30 */	{ 35, 39, 0, },
X/* 31-35 */	{ 38, 42, 59, 0, },
X/* 36-40 */	{ 40, 45, 62, 0, },
X/* 41-45 */	{ 42, 47, 64, 0, },
X/* 46-49 */	{ 44, 49, 66, 0, },
X/* 50-51 */	{ 46, 51, 68, 0, },
X/* 52-53 */	{ 48, 53, 70, 0, },
X/* 54-55 */	{ 50, 55, 71, 0, },
X/* 56-57 */	{ 52, 57, 72, 74, 84, 0, },
X/* 58-59 */	{ 54, 59, 73, 75, 85, 0, },
X/* 60-61 */	{ 56, 61, 74, 76, 86, 0, },
X/* 62-63 */	{ 58, 63, 75, 77, 87, 0, },
X/* 64-65 */	{ 60, 65, 76, 78, 88, 0, },
X/* 66-67 */	{ 62, 67, 77, 79, 88, 89, 0, },
X/* 68-69 */	{ 64, 69, 78, 80, 89, 89, 0, },
X/* 70-71 */	{ 66, 71, 79, 81, 89, 90, 0, },
X/* 72-73 */	{ 68, 73, 80, 82, 90, 90, 0, },
X/* 74-75 */	{ 70, 75, 81, 83, 90, 91, 0, },
X/* 76-77 */	{ 72, 77, 82, 84, 91, 91, 0, },
X/* 78-79 */	{ 74, 79, 83, 85, 91, 92, 0, },
X/* 80-81 */	{ 76, 81, 84, 86, 92, 92, 0, },
X/* 82-83 */	{ 78, 83, 85, 87, 92, 93, 0, },
X/* 84-85 */	{ 80, 85, 86, 88, 93, 93, 94, 0, },
X/* 86-87 */	{ 82, 86, 87, 89, 93, 94, 94, 0, },
X/* 88-89 */	{ 84, 87, 88, 90, 94, 94, 95, 0, },
X/* 90 */	{ 86, 88, 89, 91, 94, 95, 95, 97, 0, },
X/* 91 */	{ 88, 89, 90, 92, 95, 95, 96, 97, 0, },
X/* 92 */	{ 90, 90, 91, 93, 95, 96, 96, 97, 0, },
X/* 93 */	{ 91, 91, 92, 94, 96, 96, 97, 98, 0, },
X/* 94 */	{ 92, 92, 93, 95, 96, 97, 97, 98, 99, 0 },
X/* 95 */	{ 93, 93, 94, 96, 97, 97, 98, 98, 99, 0 },
X/* 96 */	{ 94, 94, 95, 97, 97, 98, 98, 99, 99, 0 },
X/* 97 */	{ 95, 95, 96, 97, 98, 98, 99, 99, 99, 0 },
X/* 98 */	{ 96, 96, 97, 98, 98, 99, 99, 99, 100, 0 },
X/* 99 */	{ 97, 97, 98, 98, 99, 99, 100, 100, 100, 0 },
X/* 100 */	{ 98, 98, 99, 99, 99, 100, 100, 100, 100, 101 },
X/* oops! */	{ -1, -1, -1, -1, -1, -01, -01, -01, -01, -01 }
X};
X
X/* table 15.13 */
Xint StatBonusTable[][3] = {
X/* 1 */		{ -25,1, 0 },
X/* 2 */		{ -20,1, 0 },
X/* 3-4 */	{ -15,1, 0 },
X/* 5-9 */	{ -10,2, 0 },
X/* 10-14 */	{ -5, 2, 0 },
X/* 15-24 */	{ -5, 3, 0 },
X/* 25-39 */	{ 0,  4, 0 },
X/* 40-59 */	{ 0,  5, 0 },
X/* 60-74 */	{ 0,  6, 0 },
X/* 75-84 */	{ 5,  7, 1 },
X/* 85-89 */	{ 5,  8, 1 },
X/* 90-94 */	{ 10, 8, 1 },
X/* 95-97 */	{ 15, 9, 2 },
X/* 98-99 */	{ 20, 9, 2 },
X/* 100 */	{ 25, 10,3 },
X/* 101 */	{ 30, 10,3 },
X/* 102+ */	{ 35, 11,4 }
X};
X
Xt_skilltable SkillTable = {
X     { ClassFighter,    {
X	  {1,-1},{1,-1},{2,-1},{2,-2},				/* armour  */
X	  {1,5}, {2,5}, {2,7}, {2,7}, {2,7}, {5,0},		/* weapons */
X	  {3,7}, {2,6}, {2,6}, {3,8}, {3,9}, {2,5}, {2,5},	/* general */
X	  {20,0},{7,0}, {9,0}, {25,0},{20,0},			/* magical */
X	  {3,8}, {3,-3},{2,6}, {20,0},{3,7}, {1,3}}},		/* special */
X     { ClassThief,	{
X	  {1,-1},{2,-2},{3,-3},{4,-4},				/* armour  */
X	  {2,7}, {3,8}, {4,0}, {4,0}, {4,0}, {6,0},		/* weapons */
X	  {2,5}, {1,3}, {2,6}, {1,3}, {1,3}, {1,3}, {1,3},	/* general */
X	  {10,0},{6,0}, {7,0}, {20,0},{20,0},			/* magical */
X	  {1,3}, {3,-3},{2,6}, {20,0},{3,7}, {3,7}}},		/* special */
X     { ClassRogue,	{
X	  {1,-1},{1,-1},{2,-2},{3,-3},				/* armour  */
X	  {2,5}, {3,8}, {3,9}, {3,9}, {3,9}, {6,0},		/* weapons */
X	  {3,7}, {2,5}, {2,5}, {2,5}, {2,6}, {1,3}, {1,3},	/* general */
X	  {8,0}, {6,0}, {8,0}, {20,0},{20,0},			/* magical */
X	  {2,5}, {3,-3},{2,6}, {20,0},{3,7}, {2,5}}},		/* special */
X     { ClassWarriorMonk,{
X	  {9,0}, {9,0}, {10,0},{10,0},				/* armour  */
X	  {4,0}, {6,0}, {8,0}, {8,0}, {8,0}, {15,0},		/* weapons */
X	  {3,7}, {1,5}, {2,7}, {3,9}, {3,9}, {2,4}, {2,5},	/* general */
X	  {10,0},{6,0}, {9,0}, {19,0},{20,0},			/* magical */
X	  {3,9}, {3,-3},{1,3}, {3,7}, {1,3}, {2,7}}},		/* special */
X     { ClassMagician,	{
X	  {9,0}, {9,0}, {10,0},{11,0},				/* armour  */
X	  {9,0}, {20,0},{20,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {6,0}, {3,0}, {3,0}, {7,0}, {8,0}, {5,0}, {3,0},	/* general */
X	  {1,-1},{1,4}, {1,4}, {7,0}, {2,5},			/* magical */
X	  {9,0}, {2,-2},{6,0}, {20,0},{9,0}, {8,0}}},		/* special */
X     { ClassIllusionist,{
X	  {9,0}, {9,0}, {10,0},{11,0},				/* armour  */
X	  {9,0}, {20,0},{20,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {7,0}, {3,0}, {3,0}, {8,0}, {8,0}, {3,0}, {2,0},	/* general */
X	  {1,-1},{1,4}, {1,4}, {7,0}, {2,6},			/* magical */
X	  {5,0}, {1,-1},{6,0}, {20,0},{9,0}, {8,0}}},		/* special */
X     { ClassAlchemist,	{
X	  {9,0}, {9,0}, {10,0},{11,0},				/* armour  */
X	  {9,0}, {20,0},{20,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {7,0}, {3,0}, {3,0}, {4,0}, {4,0}, {6,0}, {3,0},	/* general */
X	  {1,-1},{1,3}, {1,3}, {7,0}, {2,7},			/* magical */
X	  {9,0}, {1,-1},{6,0}, {20,0},{9,0}, {6,0}}},		/* special */
X     { ClassCleric,	{
X	  {1,-1},{2,-2},{10,0},{11,0},				/* armour  */
X	  {6,0}, {7,0}, {9,0}, {9,0}, {9,0}, {20,0},		/* weapons */
X	  {5,0}, {3,0}, {3,0}, {7,0}, {8,0}, {5,0}, {3,0},	/* general */
X	  {1,-1},{2,5}, {2,5}, {1,4}, {3,0},			/* magical */
X	  {9,0}, {2,-2},{5,0}, {20,0},{6,0}, {6,0}}},		/* special */
X     { ClassAnimist,	{
X	  {2,-2},{3,-3},{10,0},{11,0},				/* armour  */
X	  {6,0}, {7,0}, {9,0}, {9,0}, {9,0}, {20,0},		/* weapons */
X	  {4,0}, {3,0}, {1,3}, {8,0}, {8,0}, {3,0}, {3,0},	/* general */
X	  {1,-1},{2,6}, {2,6}, {2,5}, {3,0},			/* magical */
X	  {6,0}, {2,-2},{5,0}, {20,0},{6,0}, {4,0}}},		/* special */
X     { ClassHealer,	{
X	  {2,-2},{3,-3},{10,0},{11,0},				/* armour  */
X	  {9,0}, {20,0},{20,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {6,0}, {3,0}, {3,0}, {8,0}, {8,0}, {6,0}, {3,0},	/* general */
X	  {1,-1},{2,6}, {3,7}, {2,5}, {3,0},			/* magical */
X	  {9,0}, {2,-2},{5,0}, {20,0}, {6,0}, {1,-3}}},		/* special */
X     { ClassMentalist,	{
X	  {4,-4},{5,-5},{6,-6},{7,-7},				/* armour  */
X	  {6,0}, {8,0}, {15,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {5,0}, {3,0}, {2,0}, {7,0}, {8,0}, {5,0}, {3,0},	/* general */
X	  {1,-1},{2,5}, {2,5}, {8,0}, {2,6},			/* magical */
X	  {9,0}, {2,-2},{3,0}, {15,0},{3,0}, {6,0}}},		/* special */
X     { ClassLayHealer,	{
X	  {2,-2},{3,-3},{4,-4},{5,-5},				/* armour  */
X	  {8,0}, {8,0}, {15,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {6,0}, {3,0}, {2,0}, {8,0}, {8,0}, {6,0}, {3,0},	/* general */
X	  {1,-1},{2,6}, {2,6}, {8,0}, {2,7},			/* magical */
X	  {9,0}, {2,-2},{3,0}, {15,0}, {3,0}, {6,0}}},		/* special */
X     { ClassSeer,	{
X	  {4,-4},{5,-5},{6,-6},{7,-7},				/* armour  */
X	  {6,0}, {8,0}, {15,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {4,0}, {3,0}, {2,0}, {7,0}, {7,0}, {6,0}, {1,-1},	/* general */
X	  {1,-1},{2,6}, {2,6}, {8,0}, {2,7},			/* magical */
X	  {9,0}, {1,-1},{3,0}, {15,0}, {3,0}, {6,0}}},		/* special */
X     { ClassSorceror,	{
X	  {9,0}, {9,0}, {10,0},{11,0},				/* armour  */
X	  {9,0}, {20,0},{20,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {7,0}, {3,0}, {3,0}, {7,0}, {7,0}, {6,0}, {3,0},	/* general */
X	  {1,-1},{2,5}, {2,5}, {2,5}, {2,5},			/* magical */
X	  {9,0}, {2,-2},{5,0}, {20,0},{9,0}, {8,0}}},		/* special */
X     { ClassMystic,	{
X	  {4,-4},{5,-5},{6,-6},{7,-7},				/* armour  */
X	  {9,0}, {20,0},{20,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {7,0}, {3,0}, {3,0}, {7,0}, {7,0}, {2,0}, {2,0},	/* general */
X	  {1,-1},{2,5}, {2,5}, {8,0}, {2,6},			/* magical */
X	  {4,0}, {1,-1},{5,0}, {15,0}, {6,0}, {8,0}}},		/* special */
X     { ClassAstrologer,	{
X	  {4,-4},{5,-5},{6,-6},{7,-7},				/* armour  */
X	  {9,0}, {20,0},{20,0},{20,0},{20,0},{20,0},		/* weapons */
X	  {7,0}, {3,0}, {3,0}, {7,0}, {7,0}, {6,0}, {2,0},	/* general */
X	  {1,-1},{2,6}, {2,6}, {1,5}, {2,7},			/* magical */
X	  {9,0}, {1,-1},{5,0}, {15,0},{6,0}, {6,0}}},		/* special */
X     { ClassMonk,	{
X	  {9,0}, {9,0}, {10,0},{11,0},				/* armour  */
X	  {5,0}, {8,0}, {8,0}, {8,0}, {15,0},{15,0},		/* weapons */
X	  {3,7}, {2,6}, {3,0}, {4,0}, {4,0}, {2,7}, {2,7},	/* general */
X	  {4,-4},{4,0}, {5,0}, {13,0},{9,0},			/* magical */
X	  {4,0}, {3,-3},{2,4}, {6,0}, {2,5}, {3,7}}},		/* special */
X     { ClassRanger,	{
X	  {1,-1},{2,-2},{3,-3},{4,-4},				/* armour  */
X	  {3,7}, {4,0}, {6,0}, {6,0}, {6,0}, {9,0},		/* weapons */
X	  {3,9}, {2,6}, {2,6}, {4,0}, {4,0}, {1,5}, {2,7},	/* general */
X	  {4,-4},{5,0}, {6,0}, {3,0}, {15,0},			/* magical */
X	  {3,0}, {3,-3},{2,7}, {20,0},{4,0}, {2,7}}},		/* special */
X     { ClassBard,	{
X	  {2,-2},{3,-3},{4,-4},{5,5},				/* armour  */
X	  {3,9}, {6,0}, {7,0}, {7,0}, {7,0}, {15,0},		/* weapons */
X	  {3,9}, {2,6}, {2,6}, {4,0}, {4,0}, {2,7}, {2,7},	/* general */
X	  {4,-4},{5,0}, {6,0}, {13,0},{10,0},			/* magical */
X	  {6,0}, {1,-1},{2,7}, {15,0},{3,0}, {3,8}}}		/* special */
X};
X
X
Xstruct ClassStatWeightingTable {
X     te_cclass	cclass;
X     float weightings[NumberOfStats];
X} ClassStatWeightingTable[] = {
X     /* characterclass    Str  Qu   Pr   In   Em   Co   Ag   SD   Re   Me */
X     { ClassFighter,	{ 1.0, .01, .01, .01, .01, 1.0, .01, .01, .01, .01 } },
X     { ClassThief,	{ .01, 1.0, .01, .01, .01, .01, 1.0, .01, .01, .01 } },
X     { ClassRogue,	{ 1.0, .01, .01, .01, .01, .01, 1.0, .01, .01, .01 } },
X     { ClassWarriorMonk,{ .01, 1.0, .01, .01, .01, .01, .01, 1.0, .01, .01 } },
X     { ClassMagician,	{ .01, .01, .01, .01, 1.0, .01, .01, .01, 1.0, .01 } },
X     { ClassIllusionist,{ .01, .01, .01, .01, 1.0, .01, .01, .01, 1.0, .01 } },
X     { ClassAlchemist,	{ .01, .01, .01, .01, 1.0, .01, .01, .01, 1.0, .01 } },
X     { ClassCleric,	{ .01, .01, .01, 1.0, .01, .01, .01, .01, .01, 1.0 } },
X     { ClassAnimist,	{ .01, .01, .01, 1.0, .01, .01, .01, .01, .01, 1.0 } },
X     { ClassHealer,	{ .01, .01, .01, 1.0, .01, .01, .01, .01, .01, 1.0 } },
X     { ClassMentalist,	{ .01, .01, 1.0, .01, .01, .01, .01, 1.0, .01, .01 } },
X     { ClassLayHealer,	{ .01, .01, 1.0, .01, .01, .01, .01, 1.0, .01, .01 } },
X     { ClassSeer,	{ .01, .01, 1.0, .01, .01, .01, .01, 1.0, .01, .01 } },
X     { ClassSorceror,	{ .01, .01, .01, 1.0, 1.0, .01, .01, .01, .01, .01 } },
X     { ClassMystic,	{ .01, .01, 1.0, .01, 1.0, .01, .01, .01, .01, .01 } },
X     { ClassAstrologer,	{ .01, .01, 1.0, 1.0, .01, .01, .01, .01, .01, .01 } },
X     { ClassMonk,	{ .01, .01, .01, .01, 1.0, .01, .01, 1.0, .01, .01 } },
X     { ClassRanger,	{ .01, .01, .01, 1.0, .01, 1.0, .01, .01, .01, .01 } },
X     { ClassBard,	{ .01, .01, 1.0, .01, .01, .01, .01, .01, .01, 1.0 } }
X     /* characterclass    Str  Qu   Pr   In   Em   Co   Ag   SD   Re   Me */
X};
X
@@@End of tables.h

exit 0

-- 
Liam R. E. Quin,  lee@sq.com, {utai,utzoo}!sq!lee,  SoftQuad Inc., Toronto
Nicholas: [...]  The best/ Thing we can do is to make wherever we're lost in
Look as much like home as we can. [Christopher Fry, The Lady's Not For Burning]