INTRODUCTION

The task system is intended to regularise the use of Skills in the CDlib
based muds.  A task consists of a difficulty and a list of applicable skills.
Optionally, an opponent and an opponent's skill list may be specified.

The wizard coding a task should follow the following process

1. Define the task.  What is it exactly that is to be done?
2. Make a list of what skills and stats might possibly apply.
   If the action is done to an opponent, decide what skills and stats 
       oppose the action. 
3. Assign a difficulty.
4. Combine the skills and stats if appropriate, using the min, max and
       average functionality.
5. Implement it with a function call to resolve_task.

Example

Task : to swim across a pond
Stats : Con
Skills : Swimming
Difficulty : Simple 

block()
{
    success = resolve_task(TASK_ROUTINE, ({TS_CON, SS_SWIMMING}));
    if (success > 0) 
    {
        write("You made it.\n");
        return 0;
    }

    write("You try, but you just can't seem to keep your head above water.\n");
        return 1;
}

A more complex example:

Task : to pick a players pocket
Thief : Dex, pickpocket
Victim : Wis, awareness
Difficulty : Difficult

success = resolve_task(TASK_DIFFICULT, ({TS_DEX, SS_PICK_POCKET}),
    victim, ({TS_WIS, SS_AWARENESS}));

success > 0 implies success in both examples.  Note that you must use TS_
on stats to get the proper stats.  Otherwise, you will get the weapon skills
with the same number as the stat.

IMPLEMENTATION AND MUDLIB SUPPORT

The mudlib supports task functionality through the function
resolve_task() in the living object.  The prototype of this function is:

nomask int 
resolve_task(int difficulty, int *skill_list, 
    object opponent, int *opp_skill_list)

The return value is expressed as a percentage above the original difficulty.  
For example, suppose that the difficulty was 1000.  If the number generated 
was 1500, the function would return 50.  If the number generated was 500, 
the function would return -50.  

Interpreting this number is up to the individual wizard, but negative
numbers always imply failure, positive success.  

The 'difficulty' is any positive integer.  Normal values are defined to be:

TASK_SIMPLE      200  /*(91.96%) */
TASK_ROUTINE     500  /*(50.00%) */
TASK_DIFFICULT   800  /*( 8.04%) */
TASK_FORMIDABLE 1100  /*(Need skills to even have a chance) */
TASK_IMPOSSIBLE 1400  /*(Need even more skills to have a chance) */

These levels are intended for use when no more than 2 skills or stats
are used for modifiers.  For each extra skill or stat, 100 should be
added.  Of course, a wizard may pick his own number, if it seems right
to them.  However, using these constants should yield more consistent
results.

A 'skill list' consists of a list of the skills and stats which affect the
task at hand, possibly seperated by some constants which tell how the 
skills should be interpreted.  These constants are:

SKILL_MIN    This signals a list of skills (or stats) for which the
             minimum value is used.  The list is terminated by SKILL_END.  
SKILL_MAX    exactly the same, except that the maximum value is used.
SKILL_AVG    the average value of the numbers listed is used.
SKILL_WEIGHT the next value (or sublist) is weighted by this factor (percent)
             (may not be used inside sublists, but applies _to_ a list)

SKILL_END    This constant is used to terminate a sublist of skills

An example of a skill list using SKILL_WEIGHT and SKILL_MIN is:

{
    int *skill_list;
    /*
     * This yields a modifier of sword + 60*min(str,dex)/100
     */
    skill_list = ({ SS_SWORD, 
        SKILL_WEIGHT, 60, SKILL_MIN, TS_STR, TS_DEX, SKILL_END});
}

Note that skills range from 1-100, while stats range from 1-1000.
Most players will not have stats exceeding 150 or so, but this cannot be
relied on.  

As an example, lets say I have a spell my player wants to cast.  In the 
spell code, I might check success with the following fragment.

{
    if(this_player()->resolve_task(TASK_DIFFICULT, 
        ({SKILL_WEIGHT, 50, SS_SPELLCRAFT,
          SKILL_WEIGHT, 90, SKILL_AVG, TS_WIS, TS_INT, SKILL_END, 
          SS_FORM_CONJURATION,
          SS_ELEMENT_FIRE})) > 0)
    {
        spell_succeeds();
    }
}  

This creates a formula of:
  (50*spellcraft + 90*average(wis,int) + 100*conjuration + 100*fire)/100

for the bonus.  This effectively shifts the difficulty downwards.

TECHNICAL DETAILS
To aid you in deciding what difficulty to make your task, some
mathematical information on the way the system works is given.

The system itself is quite simple.  An approximately normally distributed 
pseudo-random number ranging from 1 to 999 (bell shaped curve) is obtained by 
summing two random numbers.  The players skills and stats add to this, 
while his opponents' subtract, yielding a net bonus.  The final number is 
compared with the difficulty.  If it is higher, the task succeeds.  
Otherwise, the task fails.  

You can consider the difficulty minus the net bonus to be the "true 
difficulty", and then you can apply the following formula to determine 
chance of success.

    pchance(x) = (x)*(x + 1)/5000              ;  0  < x <= 500
    pchance(x) = 100 - pchance(1000 - x)       ; 500 < x < 1000
    pchance(x) = 0                             ; otherwise
               
