One obvious problem I see with your attempt is rounding errors. AnyDice uses integer math, and rounds the result of division towards zero*, so for example 9 / 5 in AnyDice equals 1, not 1.8 (which is not a number AnyDice can represent).
You can partly work around this issue by multiplying your numbers by some suitably large constant factor (say, 10 or 100 or 1000) before dividing them by N
. Also, to make AnyDice round the result of division to nearest integer, instead of always down, you can replace A / B
with (2*A + B) / (2*B)
.
(To be precise, because AnyDice rounds towards zero instead of always down, that formula only works for positive results. If either the dividend or the divisor may be negative, you'll need something slightly more complicated, as shown below. Also, there still an ambiguous case when the divisor is even and the remainder is exactly half of the divisor; my code below rounds away from zero in those cases, but other choices are also possible and justifiable.)
Putting those together, you'll get something like this:
function: sum highest in ROLL:s {
MAX: 1@ROLL
COUNT: ROLL = MAX
result: COUNT * MAX
}
function: divide A:n by B:n and round to nearest {
if A < 0 { result: -[divide -A by B and round to nearest] }
if B < 0 { result: -[divide A by -B and round to nearest] }
result: (2*A + B) / (2*B)
}
loop N over {2..10} {
output [divide [sum highest in Nd10] * 1000 by N and round to nearest] named "[N]d10"
}
Of course, the results output by this code are all multiplied by 1000, so for example a result of 1667 really means 1.667, i.e. approximately 5 / 3.
If you only care about the average results, or about the general shape of the distributions instead of their exact value, there's another possible workaround that makes use of AnyDice's ability to work with probability distributions: rounding with dithering. Basically, the idea is to replace A / B
with a function that rounds the result of the division up with probability p = R / B, where R is the remainder left after dividing A by B, and down with probability 1 − p, e.g. like this:
function: sum highest in ROLL:s {
MAX: 1@ROLL
COUNT: ROLL = MAX
result: COUNT * MAX
}
function: divide A:n by B:n with dithering {
if A < 0 { result: -[divide -A by B with dithering] }
if B < 0 { result: -[divide A by -B with dithering] }
Q: A / B
R: A - Q * B
result: Q + d{1:R, 0:B-R}
}
loop N over {2..10} {
output [divide [sum highest in Nd10] by N with dithering] named "[N]d10"
}
Using this kind of dithering division will yield exactly correct averages with no rounding error** even without any multiply-by-1000 scaling tricks. However, the distributions of the actual rolled results will look "blurred", since e.g. the probability of rolling 7 / 2 = 3.5 will be spread evenly over the "3" and "4" bins in the chart. (The standard deviations in the summary view will also be off a bit, since the dithering introduces extra randomness and thus increases the variance of the results.)
*) The AnyDice documentation says "down" instead of "towards zero", but that appears to be an error in the documentation. The actual behavior is easy enough to verify.
**) Well, except for the very slight errors possibly resulting from the finite precision floating point math used by AnyDice to calculate probabilities.
I expected the first die to contribute more than the second, but further dice to start contributing more as they raise the chances of both a higher result and a higher count of it.
Looking at the results from the programs above, it seems that — even with corrected rounding — your intuition is indeed off: at least for the pool sizes AnyDice can handle, the more dice there already are in the pool, the less relative value a single extra die has.
One way of perhaps refining your intuition is to consider the limit of very large pools, where you're almost guaranteed to roll at least one 10 on nd10. Thus, your result is almost always 10 × k, where k is the number of your dice that rolled a 10.
The random number k above is binomially distributed, with an average of n / 10, where n is the number of dice in the pool. Thus, the average result of a roll of n dice is 10 × (n / 10) = n, and so adding one more die to the pool always just raises the average by one, while the average result divided by the number of dice stays the same. So in the limit of very large pools, the relative gain from one extra die, divided by the number of dice already in the pool, tends to zero!
Of course, for smaller pools, there's also a non-negligible change of rolling no tens at all, and thus adding more dice raises the probability of rolling a higher max value. The effects of this are more complicated to calculate, since raising the value of the highest roll is not always beneficial: a roll of (1, 5, 7, 7) → 14 is better than a roll of (1, 5, 7, 7, 10) → 10.
Based on experimenting with your code (specifically, removing the division entirely and varying the size of the pool and the number of sides on the dice) it seems that as the pool size increases starting from one die, there are (at least for large enough dice) three qualitatively different phases:
At first, when the number of dice is very small compared to the number of sides on each die, doubles are unlikely (and double highest rolls even less likely) and thus the average result is mostly determined by the average of the highest number rolled. The first few additional dice each raise the average by more than 1, but each additional die raises the average by a smaller amount than the previous one.
As the number of dice in the pool gets large enough, the average gain from each additional die drops below one. For 10-sided dice this happens at 4d10: the fourth die increases the average by 10.13 − 9.07 = 1.06, but the fifth only by 11.04 − 10.13 = 0.91.
As the number of dice increases further, the gain from each additional die eventually reaches a minimum somewhere between 0 and 1 and then starts slowly rising again as the average result approaches the asymptote where, for large n, the average result from rolling n dice and taking the sum of the highest rolls simply equals n as described above.
(For 10-sided dice the minimum gain per additional die seems to occur at 10d10, with the 10th die increasing the average by only 0.7456 points, compared to 0.7502 for the 9th die and 0.7457 points for the 11th. This is right at the limit of what AnyDice can calculate without timing out, but I'm confident that for larger pools the average gain from one extra die will indeed slowly rise and approach one asymptotically.)
Basically, when the number of dice rolled is much larger than the number of sides per die, the binomial approximation described above holds well and the average result is simply equal to the number of dice rolls. But for smaller numbers of dice there is a "bump" in the averages, caused by the fact that even rolls where none of the dice rolls the highest possible result can still score a decent number of points based on the highest number actually rolled (and any possible duplicates of it).