Skills:

Skills are intended to be a measure of how good players become at
performing certain tasks- types of spells, types of combat actions, etc.
The higher the skill, the higher the chance of the action succeeding, 
but the higher the skill, the harder it is to raise it higher.  To 
raise a skill, it must first be practiced by use, then trained by someone 
more skilled.  This could be an NPC, or it might be possible, for a high 
cost, to train oneself, and then train others. Or a combination of both.  
The code I describe below leaves that part up to the wizard using it.

Skills have the following components (default value)
  1) name
  2) level (1)
  3) use_attrib - attribute that gives a bonus/penalty to skill use
  4) practice_attrib - attribute that gives a bonus/penalty to wether
  uses become a practice
  5) practices
  6) use_difficulty  (100)
  7) practice_difficulty_success (75) - the chance of a successful use
  becoming a practice
  8) practice_difficulty_failure (25) - same, but for a failure
  9) train_difficulty (10) - how many practices before training
 10) train_cost (100) - how much experience it costs to train the skill


Here are detailed explanations:

Name:
  Doesn't really need an explanation, except that it should be a purely
  alphanumeric string.
Level:
  Basically, how many times the skill has been trained, and how likely it
  is to succeed
Use_attrib:
  * use_attrib_bonus = use_attrib - 15
  A single attribute that determines a bonus or penalty to a skill check.
  For Nirvana's current attrib system, subtract 15 from the attrib to get
  the penalty/bonus
Practice_attrib
  * practice_attrib_bonus = practice_attrib -15
  See the description for use_attrib
Practices:
  See train_difficulty below for an explanation of what these are used for
Use_difficulty:
  * skill_roll = random(level)
  * difficulty_roll = random(use_difficulty)
  if skill_roll + use_attrib_bonus >= difficulty roll, the skill is used
  successfully, otherwise, it fails however, if difficulty_roll is
  use_difficulty-1, the skill always fails if difficulty_roll is 0, the skill
  always succeeds
Practice_difficulty_success
  * practice_roll = random(practice_difficulty_success)
  * difficulty_roll = random(100);
  if practice_roll+practice attrib_bonus > difficulty_roll then a practice
  is counted there are no special rules for 0s or maximums here the default
  value of 75 means about a 40% success rate, if the player passes the skill
  check in the first place. (modified by the bonus, of course)
Practice_difficulty_failure
  calculated just like practice_difficulty_success
  the default value of 25 means a success rate of about 15%
Train_difficulty
  * train_difficulty_divisor = 10 [if necessary, this can be made customizable]
  * practices_required = 
  level * (train_difficulty + train_difficulty*level/train_difficulty_divisor)
  To train a skill, the player needs to have met the practices_required for
  his level.  The default value of 10 means 11 at skill level 1 (to get to
  level 2), 200 at skill level 10, 600 at skill level 20, 1200 at skill
  level 30 With a train_difficulty of 50, it'd be 6000 at level 30 (that's a
  lot of skill checks)
 Train_cost
  * train_cost_divisor = 10
  * experience_required = 
  level * (train_cost + train_cost*level/train_cost_divisor)
  Obviously the default value of 100 means 110 at level 1, 12000 at level 30.


What success or failure means is entirely up to the function calling the
skill check.  It could mean anything from total failure at the action being
attempted if the skill check fails, to a slight increase in spell cost if
the skill check fails..  Skills allow a way for a player to become better at
something beyond what's recorded by levels and guild levels.

Here's a possible example.  A player in a fighting guild has a sword skill,
with all the defaults mentioned above.  He's got a skill level of 30.  The
attrib for use is strength (at 20), and the attrib for practice is will power
(at 10)

so, for using the skill, he needs random(30)+5 > random(100)  For the moment
we'll ignore the min/max rules.

If the skill check succeeds, he gets, say, +5 to his damage.  He also gets
a chance at a practice in that skill.  For that, he needs 
random(75)-5 > random(100).  There's a pretty good chance of that, so he'd
get 1 point toward the 1200 practices he needs to advance the skill.

If the skill check fails, he gets no damage bonus, but he still has a chance
at a practice:  random(25)-5 > random(100)

When he gets his 1200 practices, he goes and finds a trainer, and spends
12000 experience to raise the skill to 31.

Note that since there's always a chance of failure, there's no reason for
any kind of skill cap.  Even with a skill level of 1000, (which would take
an ungodly number of practices and experience) there's a fail chance of about
5%, and there's always a fail chance from the max difficulty roll rule.

Finally, note that practices don't carry over.  They're reset to 0 when
the skill is trained.

After inheriting/implementing the skill object, the following functions are
available.  A * marks an optional argument, but if you want to modify one of
the default values, set them all, just to be safe.  The object should be
inhereited by a guild object that saves player information to a file, as the
skill information is contained in an array.  The bulk of the work is done by a
single master object.  The skills themselves are meant to be handled by the
player object, but it can be adapted to be inherited by a guild object
instead.

Name is a string, use_attrib and practice_attrib are the first three letters
of the attrib name, and the other arguments are integers.

add_skill(name,use_attrib,practice_attrib,*use_difficulty,
         *practice_difficulty_success,*practice_difficulty_failure,
         *train_difficulty,*train_cost)
  should be pretty obvious what this does.
  returns 1 for success, 0 for failure because of bad values, and -1
  if the skill already exists

remove_skill(name) - ditto, probably won't be used much 1 for success,
  0 for failure

check_skill(name,*bonus/penalty) - checks the skill as described above, with
  the addition of the bonus/penalty to the use_difficulty check.  use the
  bonus/penalty for situations where the skill would be especially easy or
  hard to use.  returns 1 for success, 0 for failure.

query_skill_information() - return a friendly array in the following
  format:  
  ({skill_name,skill_level,% of practices to next level,skill_name...})
  use this to display a list of skills to the player.

query_skill_whatever(name) - replace whatever with something like name,
  train_cost, etc shouldn't be much use for this except query_skill_level
  but they might as well be there

set_skill_whatever(name) - same as above except it changes values.  should
  be used sparingly but a quest might grant some skill levels- for example,
  a newbie guild quest might boost a skill level to 5, which would make it
  quite a bit more useful
  returns 0 if there's no such skill, -1 if the command fails for some reason
  (you can't set negative values, or an attrib that doesn't exist) and 1 for
  success

check_skill_advance(name) - use this to see if a skill is ready to
  be advanced.  It's not just a 1 or 0 deal though so it's important to
  be careful in how you check it.
  No such skill: return 0;
  Enough practices and experience to advance: return 1;
  Not enough practices to advance: return -1;
  Enough practices, but not enough experience: return -2

advance_skill(name) -
  If the player has enough practices and experience, it deducts the
  experience, resets the practices, and raises the skill level.
  success: return 1;
  no such skill: return 0;
  skill exists, but isn't ready to be raised: return -1;
  (seperate so you can check to see if a skill is ready without
  automatically spending the experience)
  