# Roll my D&D character's ability scores

In Dungeons and Dragons, some of the most important atributes of a character are the ability scores. There are 6 ability scores, for the six abilities. The abilities are Strength, Dexterity, Constitution, Intelligence, Wisdom and Charisma.

When determining the scores for a character, I use the following procedure: Roll 4d6, drop the lowest, in any order. What this means is that I roll 4 six sided dice, ignore the lowest result, and sum the other 3. This is done 6 times. The resulting numbers are assigned to the abilities in any way I please.

The system I use for assigning scores to abilities is to assign the highest score to my character's most important skill, which depends on my character's class, assign the second highest score to Constitution, since everyone needs Constitution, and assign the other four scores arbitrarily.

Here's a table of the most important skills for various classes:

Bard - Charisma
Cleric - Wisdom
Druid - Wisdom
Fighter - Stregth
Monk - Wisdom
Rogue - Dexterity
Sorcerer - Charisma
Wizard - Intelligence


Challenge: I'll give you (as input) the first letter of my character's class (In uppercase). I'd like you to roll the abilities scores and assign them to the abilities as described above, and then output them in the order Strength, Dexterity, Constitution, Intelligence, Wisdom, Charisma.

Example:

Input: R
Rolls: 4316 3455 3633 5443 2341 6122
Scores: 13 14 12 13 9 10
Ordering: Highest goes to dexterity. Second goes to Constitution.
Output: 13 14 13 12 9 10
or
Output: 9 14 13 10 12 13
or etc.


Output may be given in any format where the numbers are clearly separated and in the proper order.

Shortest code in bytes wins. Standard loopholes banned.

# CJam, 4341 40 bytes

{6a4*:mr$0Zt:+}6*]$2m<"FRXWCDM"r#4e<3e\p


Thanks to @Sp3000 for golfing off 1 byte.

Try it online in the CJam interpreter.

### How it works

{             }6*                       e# Repeat 6 times:
6a4*                                   e#   Push [6 6 6 6].
:mr                                e#   Replace each six with a pseudo-randomly
e#   generated integer in [0 ... 5].
$e# Sort the results. 0Zt e# Replace the lowest result by 3. :+ e# Add all four integers ] e# Wrap the 6 generated integers in an array.$                      e# Sort.
2m<                   e# Rotate 2 units to the left to assign the
e# second highest result to Constitution.
"FRXWCDM"          e# Push that string.
r#        e# Find the index of the input.
e# The string doesn't contain B, P or S, so
e# those push -1.
4e<     e# Truncate the index at 4. This way, C, D
e# M all push 4.
3e\  e# Swap the integer at that index with the
e# one at index 3, i.e., the highest one.
p e# Print.


# Python 3, 137 bytes

from random import*
S=sorted
*L,c,h=S(3+sum(S(map(randrange,[6]*4))[1:])for _ in[0]*6)
L[:"FRW BPS".find(input())]+=h,
L[:2]+=c,
print(L)


Outputs a list of integers, e.g. [14, 9, 13, 12, 12, 13] for F.

The mapping from the input char to assignments turned out to be surprisingly nice. First we start by having L contain the lowest 4 rolls, after which we want to insert

• The highest roll into the correct position based on the input, then
• The second-highest roll into index 2, for Constitution.

For each input, the indices we want for the highest rolls are:

Index    Ability          Input(s)
----------------------------------
0        Strength         F
1        Dexterity        R
2        Intelligence     W
3        Wisdom           CDM
4        Charisma         BPS


Amazingly, we only need "FRW BPS".find(input()) for this, because:

• FRW work as expected, giving their respective indices,
• CDM are not present so find gives -1, which for a 4-element list is index 3, and
• BPS give 4, 5, 6 respectively, but it doesn't matter if we overshoot because we can only append an element at the end.

# J, 100 97 bytes

(0;0,b)C.^:(b>0)(0;1 2)C.\:~+/"1]1}."1/:~"1]1+?6 4$4$6[b=.('BCDFMPRSW'i.1!:1[1){5 4 4 0 4 5 1 5 3


Takes input in STDIN

• I hear Prolog is getting jealous... – Alex A. Jul 10 '15 at 16:40
• @AlexA. We're just taking a break, I can try something else in the meanwhile... – Fatalize Jul 10 '15 at 16:43

# C++ - 387 bytes

First attempt here, more golfing required, particularly in determining what class is being used.

Golfed:

#include<cstdlib>
#include<cstdio>
#include<time.h>
int main(int c,char**v){char*o=*v,l=*v[1];int b=-1,s=-1,i=6,x=0,q=l>=67&&l<=68||l==77?4:l==70?0:l==87?3:l==82?1:5;srand(time(0));for(;i-->0;){int w=9,d=4,u=3,t;for(;d-->0;){t=rand()%6;if(t<w){u+=w<9?w:0;w=t;}else u+=t;}if(u>s){c=s;s=u;u=c;}if(s>b){c=s;s=b;b=c;}if(u>=0)o[x++]=u;}for(i=0;i<6;i++)printf("%d ",i==2?s:(i==q?b:o[--x]));}


Rather ungolfed:

#include<cstdlib>
#include<cstdio>
#include<time.h>
int main(int c,char**v)
{
//name of program must be at least 4 chars
char*others=*v,clas=*v[1];
int desired = clas>=67&&clas<=68||clas==77?4:clas==70?0:clas==87?3:clas==82?1:5; //TODO:

srand(time(0));
int best=-1,second=-1,i=6,otherIndex=0;
for(;i-->0;)
{
int lowest=9,diecount=4,sum=3;
for(;diecount-->0;)
{
int loc=rand()%6;
if (loc<lowest)
{
sum+=lowest<9?lowest:0;
lowest=loc;
}
else
{
sum+=loc;
}
}
if(sum>second)
{
c=second;second=sum;sum=c;
}
if(second>best)
{
c=second;second=best;best=c;
}
if(sum>=0)
{
others[otherIndex++]=sum;
}
}

for(i=0;i<6;i++)
{
printf("%d ",i==2?second:(i==desired?best:others[--otherIndex]));
}

getchar();
}