Not sure how much js can be in a sheet, but here is the "best" side of a roll, generated for using 0, 1, 2, and 3 chance points... NOTE: I wrote this to be a console proof-of-concept version, so I didn't use Roll20 functions like log() and randomInteger() ... especially since I'm not sure which of those map over to the character sheet environment. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 const getD10 = () => { return 1 + Math .floor( Math .random()* 10 );};
let numD10 = 5 ;
let baseroll = [... Array (numD10)].map((e, i) => 1 + Math .floor( Math .random()* 10 )).sort((a,b) => a - b);
console.log(baseroll);
const getBest = (a, k = 3 , curbest = baseroll.length * 10 ) => {
let o = a.reduce((m,v) => {
m[v] = (m[v] || 0 ) + 1 ;
return m;
},{});
const buildbest = (key = 0 ) => {
let avkeys = Object .keys(o);
let w = o[avkeys[key]];
let total = parseInt (avkeys[key]);
avkeys = avkeys.filter((e,i) => i !== key);
while (w < k) {
w += parseInt (o[avkeys[ 0 ]]);
total += parseInt (avkeys.shift());
}
return total;
};
let best = baseroll.reduce((m,v,i) => {
if (i > Object .keys(o).length- 1 ) return m;
let temp = buildbest(i);
return temp < m ? temp : m;
},curbest);
return best;
};
const chanceBest = (chance) => {
let rollSet = [];
const permutaterolls = (c, r = baseroll) => {
if (c=== 0 ) return ;
r.forEach((e,i) => {
let [incr, decr] = [[...r],[...r]];
incr[i] = ++incr[i];
rollSet.push(incr);
permutaterolls(c- 1 , incr)
decr[i] = --decr[i];
rollSet.push(decr);
permutaterolls(c- 1 , decr);
});
};
permutaterolls(chance);
let rollSetObj = rollSet
.filter(e => e.reduce((m,e1) => { m = m && (e1 >= 1 && e1 <= 10 ); return m; }, true ))
.map(e => e.sort((a,b) => a - b))
.reduce((m,e) => {
m[e.join( '' )] = e;
return m;
}, {});
return Object .keys(rollSetObj).map(e=>rollSetObj[e]);
};
const Results = () => {
let best0 = getBest(baseroll);
let best1 = chanceBest( 1 ).reduce((m,v) => {
let temp = getBest(v);
return temp < m ? temp : m;
},best0);
let best2 = chanceBest( 2 ).reduce((m,v) => {
let temp = getBest(v);
return temp < m ? temp : m;
},best1);
let best3 = chanceBest( 3 ).reduce((m,v) => {
let temp = getBest(v);
return temp < m ? temp : m;
},best2);
return {
Best0: best0,
Best1: best1,
Best2: best2,
Best3: best3
};
};
console.log(Results()); Drop that into your console (or your favorite emulator), and run it a bunch of times. It will give you the best option for the roll with each increment of chance you spend. Even given my log statements, blank lines, and the generation of the roll, it's still only 77 lines. I'll leave it to you to reverse it for the "worst" option.