# Talk:Role
The game and the guidebook refer to the class as the role. I suggest we change it accordingly in the articles of this wiki, too. --ZeroOne 23:53, 24 March 2006 (UTC)
Most of these role pages omit any mention of that roles' speciality spell.--PeterGFin 18:28, 28 April 2007 (UTC)
This should be a huge page. It's one of the most important features of NetHack. It should have a discussion on the differences in roles, each roles special spell, and role difficulty should be merged to this article. And please don't say, "Do it yourself, moron!" because I'm exceedingly lazy and then I'll do it, and it will be shoddy work since I barely know anything at all. Grognor 18:06, 8 June 2007 (UTC)

slashem role table is flat wrong
The table of permissible role/race/alignment combinations seems to be flat wrong. Starting with the first line, the table asserts human,elf,dwarf,gnome,doppelganger, while the code says MH_HUMAN|MH_ELF|MH_DWARF|MH_GNOME|MH_HOBBIT|MH_VAMPIRE. I'm not changing things because I can't wiztest. --Tjr 07:23, 19 August 2011 (UTC)

You don't need to wiztest.  Just start a char and see what races you can start as --Elronnd (talk) 05:41, 10 April 2015 (UTC)Elronnd
Attributes table
I have re-done the attributes table.  The original table of medians was by User:Derekt75 in Special:Diff/72680, but some of the values seem strange, such as Rangers having median 10 Int and Wis.  Not having Derekt75's simulation code, I wrote my own simulation program, but mine calculates the mean and standard deviation instead, which I believe are more useful than only the median.  For verifiability, I am including my code below.  I used n=10000000 samples for my simulations. Cathartes (talk) 05:54, 6 May 2022 (UTC)

Initial attribute simulation code

/* attrsim.c */
/* Example usage: attrsim wiz h 10000000 */
#include 

<stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <time.h>

enum attrib_types {
    A_STR = 0,
    A_INT,
    A_WIS,
    A_DEX,
    A_CON,
    A_CHA,

    A_MAX
};

struct role {
    char *name;
    unsigned char attrbase[A_MAX];
    unsigned char attrdist[A_MAX];
};

/* attribute order: Str Int Wis Dex Con Cha */
/* max attributes.  STR of 18/x is 18+x. */
unsigned char attrmax_human[A_MAX] = { 118, 18, 18, 18, 18, 18 };
unsigned char attrmax_elf[A_MAX] = { 18, 20, 20, 18, 16, 18 };
unsigned char attrmax_dwarf[A_MAX] = { 118, 16, 16, 20, 20, 16 };
unsigned char attrmax_gnome[A_MAX] = { 68, 19, 18, 18, 18, 18 };
unsigned char attrmax_orc[A_MAX] = { 68, 16, 16, 18, 18, 16 };

/* from role.c */
struct role roles[] = {
    {
        "arc",
        { 7, 10, 10, 7, 7, 7 },
        { 20, 20, 20, 10, 20, 10 },
    },
    {
        "bar",
        { 16, 7, 7, 15, 16, 6 },
        { 30, 6, 7, 20, 30, 7 },
    },
    {
        "cav",
        { 10, 7, 7, 7, 8, 6 },
        { 30, 6, 7, 20, 30, 7 },
    },
    {
        "hea",
        { 7, 7, 13, 7, 11, 16 },
        { 15, 20, 20, 15, 25, 5 },
    },
    {
        "kni",
        { 13, 7, 14, 8, 10, 17 },
        { 30, 15, 15, 10, 20, 10 },
    },
    {
        "mon",
        { 10, 7, 8, 8, 7, 7 },
        { 25, 10, 20, 20, 15, 10 },
    },
    {
        "pri",
        { 7, 7, 10, 7, 7, 7 },
        { 15, 10, 30, 15, 20, 10 },
    },
    {
        "rog",
        { 7, 7, 7, 10, 7, 6 },
        { 20, 10, 10, 30, 20, 10 },
    },
    {
        "ran",
        { 13, 13, 13, 9, 13, 7 },
        { 30, 10, 10, 20, 20, 10 },
    },
    {
        "sam",
        { 10, 8, 7, 10, 17, 6 },
        { 30, 10, 8, 30, 14, 8 },
    },
    {
        "tou",
        { 7, 10, 6, 7, 7, 10 },
        { 15, 10, 10, 15, 30, 20 },
    },
    {
        "val",
        { 10, 7, 7, 7, 10, 7 },
        { 30, 6, 7, 20, 30, 7 },
    },
    {
        "wiz",
        { 7, 10, 7, 7, 7, 7 },
        { 10, 30, 10, 20, 20, 10 },
    },
};

int
rn2(int x)
{
    return rand()&nbsp;% x;
}

/* based on init_attr() in attrib.c */
void
init_attr(unsigned char result[A_MAX],
          const unsigned char attrbase[A_MAX],
          const unsigned char attrdist[A_MAX],
          const unsigned char attrmax[A_MAX],
          int np)
{
    int i, x, tryct;

    for (i = 0; i &lt; A_MAX; i++) {
        result[i] = attrbase[i];
        np -= attrbase[i];
    }
    tryct = 0;
    while (np &gt; 0 &amp;&amp; tryct &lt; 100) {
        x = rn2(100);
        for (i = 0; (i &lt; A_MAX) &amp;&amp; ((x -= attrdist[i]) &gt; 0); i++)
            ;
        if (i &gt;= A_MAX)
            continue; /* impossible */

        if (result[i] &gt;= attrmax[i]) {
            tryct++;
            continue;
        }
        tryct = 0;
        result[i]++;
        np--;
    }

    /* additional adjustment from u_init.c */
    /* None of the base starting attributes are less than 5, so
       this won't make any attribute less than the minimum of 3 */
    for (i = 0; i &lt; A_MAX; i++) {
        if (!rn2(20)) {
            int xd = rn2(7) - 2;
            result[i] += xd;
            if (result[i] &gt; attrmax[i]) {
                result[i] = attrmax[i];
            }
        }
    }
}

void
do_sim(double mean[A_MAX], double stdev[A_MAX], struct role *role,
       const unsigned char *attrmax, int n)
{
    int i;

    unsigned char (*result)[A_MAX] = malloc(n * sizeof *result);
    double sum[A_MAX] = {0};
    for (i = 0; i &lt; n; i++) {
        init_attr(result[i], role-&gt;attrbase, role-&gt;attrdist, attrmax, 75);
        int j;
        for (j=0; j&lt;A_MAX; j++) {
            sum[j] += result[i][j];
        }
    }
    for (i = 0; i &lt; A_MAX; i++) {
        mean[i] = sum[i] / n;
    }
    double sqsum[A_MAX] = {0};
    for (i = 0; i &lt; n; i++) {
        int j;
        for (j = 0; j &lt; A_MAX; j++) {
            double dev = result[i][j] - mean[j];
            sqsum[j] += dev * dev;
        }
    }
    for (i = 0; i &lt; A_MAX; i++) {
        stdev[i] = sqrt(sqsum[i] / (n - 1));
    }
    free(result);
}

int
main(int argc, char *argv[])
{
    if (argc&nbsp;!= 4) {
        fprintf(stderr, "usage: %s role race n\n", argv[0]);
        return EXIT_FAILURE;
    }
    int n = atoi(argv[3]);
    struct role *role = NULL;
    size_t i;
    for (i = 0; i &lt; (sizeof roles / sizeof *roles); i++) {
        if (!strcmp(argv[1], roles[i].name)) {
            role = &amp;roles[i];
        }
    }
    if (!role) {
        fprintf(stderr, "invalid role %s\n", argv[1]);
        return EXIT_FAILURE;
    }
    const unsigned char *attrmax = attrmax_human;
    switch (argv[2][0]) {
    case 'h':
    default:
        attrmax = attrmax_human;
        break;
    case 'd':
        attrmax = attrmax_dwarf;
        break;
    case 'e':
        attrmax = attrmax_elf;
        break;
    case 'g':
        attrmax = attrmax_gnome;
        break;
    case 'o':
        attrmax = attrmax_orc;
        break;
    }

    srand(time(NULL));

    double mean[A_MAX];
    double stdev[A_MAX];
    do_sim(mean, stdev, role, attrmax, n);

    printf("Str:&nbsp;%.2f±%.2f\n"
           "Dex:&nbsp;%.2f±%.2f\n"
           "Con:&nbsp;%.2f±%.2f\n"
           "Int:&nbsp;%.2f±%.2f\n"
           "Wis:&nbsp;%.2f±%.2f\n"
           "Cha:&nbsp;%.2f±%.2f\n",
           mean[A_STR], stdev[A_STR],
           mean[A_DEX], stdev[A_DEX],
           mean[A_CON], stdev[A_CON],
           mean[A_INT], stdev[A_INT],
           mean[A_WIS], stdev[A_WIS],
           mean[A_CHA], stdev[A_CHA]);

    return EXIT_SUCCESS;
}

</time.h></math.h></stdio.h></string.h></stdlib.h>