.com.unity Forums
  The Official e-Store of Shrapnel Games

This Month's Specials

Raging Tiger- Save $9.00
winSPMBT: Main Battle Tank- Save $5.00

   







Go Back   .com.unity Forums > Illwinter Game Design > Dominions 2: The Ascension Wars

Reply
 
Thread Tools Display Modes
  #1  
Old December 31st, 2003, 08:16 PM
Saber Cherry's Avatar

Saber Cherry Saber Cherry is offline
Major General
 
Join Date: Oct 2003
Location: Crystal Tokyo
Posts: 2,453
Thanks: 0
Thanked 0 Times in 0 Posts
Saber Cherry is on a distinguished road
Default Dominions Dice Roll Chart

The old thread got deleted accidentally, but here's the crucial element

This is a chart of the probability that the difference between two dice rolls will meet or exceed the listed number. Each dice roll is a 2d6*, or 2d6 upwardly-open pair.

How to use the chart: An example.

What is the probability that a light infantry (att=10) will hit a soulless (def=2, after applying the "fist" penalty)? The difference is (2-10) = -8, but hitting requires you to beat, not just meet, the enemy defense roll. So the roll difference must be at least (2-10)+1 = -7. Looking at the "-7+" row, you see that a light infantry has an 91.8% chance of hitting a soulless.

The reverse case:

Soulless has att=3 after applying the fist -1 att penalty, and a light infantry has def=12. So for a soulless to hit, it must score a differential roll of (12-3)+1 = 10. Looking at the "10+" row, a soulless has a 4.6% chance of striking a light infantry.

The chart can also be used for damage versus protection rolls, poison rolls, and probably morale and magic resist rolls. Almost all Dominions dice rolls seem to be of the form ((2d6* + attacker's modifier) - (2d6* + defender's modifier)), which this chart describes.


Testing (2d6*, labelled 0-5, offset=2) over 200000000 rolls.

Reverse-Cumulative Difference Statistics:

-30+: 99.994%
-29+: 99.992%
-28+: 99.988%
-27+: 99.984%
-26+: 99.978%
-25+: 99.969%
-24+: 99.957%
-23+: 99.941%
-22+: 99.918%
-21+: 99.887%
-20+: 99.844%
-19+: 99.785%
-18+: 99.705%
-17+: 99.596%
-16+: 99.447%
-15+: 99.244%
-14+: 98.969%
-13+: 98.601%
-12+: 98.106%
-11+: 97.442%
-10+: 96.554%
-9+: 95.373%
-8+: 93.822%
-7+: 91.805%
-6+: 89.194%
-5+: 85.852%
-4+: 81.605%
-3+: 76.281%
-2+: 69.830%
-1+: 62.391%
0+: 54.222%
1+: 45.773%
2+: 37.605%
3+: 30.165%
4+: 23.714%
5+: 18.388%
6+: 14.145%
7+: 10.802%
8+: 8.191%
9+: 6.174%
10+: 4.624%
11+: 3.444%
12+: 2.556%
13+: 1.894%
14+: 1.399%
15+: 1.031%
16+: 0.755%
17+: 0.553%
18+: 0.404%
19+: 0.295%
20+: 0.215%
21+: 0.156%
22+: 0.113%
23+: 0.082%
24+: 0.060%
25+: 0.043%
26+: 0.031%
27+: 0.023%
28+: 0.016%
29+: 0.012%
30+: 0.008%


-Cherry
__________________
Cherry
Reply With Quote
  #2  
Old January 1st, 2004, 01:13 AM

alexti alexti is offline
First Lieutenant
 
Join Date: Dec 2003
Location: Calgary, Canada
Posts: 762
Thanks: 0
Thanked 0 Times in 0 Posts
alexti is on a distinguished road
Default Re: Dominions Dice Roll Chart

Interesting... The chart doesn't exactly match the numbers I got myself. The numbers are quite close though. I would post my formula, but I can't even think of trying to type in HTML

===========================================
Probability of roll of 2 being greater than (%) another roll of 2 by at least:
0000 = 0.542274 (54.227)
0001 = 0.457726 (45.773)
0002 = 0.376093 (37.609)
0003 = 0.301668 (30.167)
0004 = 0.237204 (23.720)
0005 = 0.183916 (18.392)
0006 = 0.141480 (14.148)
0007 = 0.108034 (10.803)
0008 = 0.081930 ( 8.193)
0009 = 0.061737 ( 6.174)
0010 = 0.046242 ( 4.624)
0011 = 0.034446 ( 3.445)
0012 = 0.025564 ( 2.556)
0013 = 0.018930 ( 1.893)
0014 = 0.013990 ( 1.399)
0015 = 0.010305 ( 1.031)
0016 = 0.007552 ( 0.755)
0017 = 0.005520 ( 0.552)
0018 = 0.004034 ( 0.403)
0019 = 0.002948 ( 0.295)
0020 = 0.002151 ( 0.215)
0021 = 0.001560 ( 0.156)
0022 = 0.001130 ( 0.113)
0023 = 0.000819 ( 0.082)
0024 = 0.000594 ( 0.059)
0025 = 0.000431 ( 0.043)
0026 = 0.000310 ( 0.031)
0027 = 0.000223 ( 0.022)
0028 = 0.000161 ( 0.016)
0029 = 0.000116 ( 0.012)
0030 = 0.000084 ( 0.008)
0031 = 0.000060 ( 0.006)
0032 = 0.000043 ( 0.004)
0033 = 0.000031 ( 0.003)
0034 = 0.000022 ( 0.002)
0035 = 0.000016 ( 0.002)
0036 = 0.000011 ( 0.001)
0037 = 0.000008 ( 0.001)
0038 = 0.000006 ( 0.001)
0039 = 0.000004 ( 0.000)
Reply With Quote
  #3  
Old January 1st, 2004, 05:52 AM
Saber Cherry's Avatar

Saber Cherry Saber Cherry is offline
Major General
 
Join Date: Oct 2003
Location: Crystal Tokyo
Posts: 2,453
Thanks: 0
Thanked 0 Times in 0 Posts
Saber Cherry is on a distinguished road
Default Re: Dominions Dice Roll Chart

Quote:
Originally posted by alexti:
Interesting... The chart doesn't exactly match the numbers I got myself. The numbers are quite close though. I would post my formula, but I can't even think of trying to type in HTML
Well, they're the same to 4 digits, which is about all I'd expect with 200 million rolls. You actually have a statistical formula that predicts the outcome, without simulation? That would be quite useful and speed up the combat simulator a lot

Oh... also... it seems that the rounding of the Last digit may differ... all my numbers are rounded up for 5-9, and down for 0-4.

[ January 01, 2004, 03:55: Message edited by: Saber Cherry ]
__________________
Cherry
Reply With Quote
  #4  
Old January 1st, 2004, 07:21 AM

alexti alexti is offline
First Lieutenant
 
Join Date: Dec 2003
Location: Calgary, Canada
Posts: 762
Thanks: 0
Thanked 0 Times in 0 Posts
alexti is on a distinguished road
Default Re: Dominions Dice Roll Chart

Quote:
Originally posted by Saber Cherry:
quote:
Originally posted by alexti:
Interesting... The chart doesn't exactly match the numbers I got myself. The numbers are quite close though. I would post my formula, but I can't even think of trying to type in HTML
Well, they're the same to 4 digits, which is about all I'd expect with 200 million rolls.
Maybe the difference is down to the random number generator you're using. Pseudo-random number generator does not give exactly correct distribution, I wonder if you'd get a bit different results with another RNG.

Quote:
You actually have a statistical formula that predicts the outcome, without simulation? That would be quite useful and speed up the combat simulator a lot
Yes, here's it:

A(m): { n1, n2: n1+n2=m, where n1,n2 independent illwinter dice rolls }
pA(m) = (q^(u+1))*{u(6-v(1-q)-q)+q(v-1)}, where u and v, such that m=5u+v and, u>=0 and v=1..5

B(m): { n1, n2: n1+n2>=m, where n1,n2 independent illwinter dice rolls }
pB(m) = (q^(u+1)*{u(20-5(v-1)(14-v)/12)+6-(v-1)(v-2)/12}

D(m): { n1, n2, n3, n4: n1+n2>=n3+n4+m, where n1,n2,n3,n4 independent illwinter dice rolls }
pD(m) = sum[s=1..5-v]f[s,u,s+v] + sum[s=6-v..5]f(s,u+1,s+v-5)
where u and v, such that m=5u+v and, u>=0 and v=1..5
and f(s,u,w) = (q^(u+2)){c2(q^2)*a1(s)*b2(u,w)+c1(q^2)*(a1(s)*b2( u,w)+a2(s)*b1(w))+c0(q^2)*a2(s)*b2(u,w)},
and
a1(s) = 6-s(1-q)-q
a2(s) = q(s-1)
b1(w) = 20 - 5(w-1)(14-w)/12
b2(u,w) = u*b1(w) + 6 - (w-1)(w-2)/12
c0(q) = 1/(1-q)
c1(q) = q/((1-q)^2)
c2(q) = (q+q^2)/((1-q)^3)

Hard to write formulas here I had to be creative in a few places. Hopefully it's understandable. For interested, I was just writing sequences of probabilities of various outcomes, writing roll results in 5u+v form and then getting summing by v in from of summing by u, summing by u is from 0 to infinity so I could roll it in (see c0,c1,c2 constants) and only leave summing from 1 to 5.

If you want I can send you code that implements it too.

Quote:
Oh... also... it seems that the rounding of the Last digit may differ... all my numbers are rounded up for 5-9, and down for 0-4.
I'm using double float precision (15 digits) and only round when outputing the text, rounding is mathematical (same as yours).

P.S. Edited: fixed missed parametrization of Ci(q)

[ January 01, 2004, 05:58: Message edited by: alexti ]
Reply With Quote
  #5  
Old January 1st, 2004, 08:39 AM
Saber Cherry's Avatar

Saber Cherry Saber Cherry is offline
Major General
 
Join Date: Oct 2003
Location: Crystal Tokyo
Posts: 2,453
Thanks: 0
Thanked 0 Times in 0 Posts
Saber Cherry is on a distinguished road
Default Re: Dominions Dice Roll Chart

In contrast, my inexact code is quite short=)

For a single open or closed die:
code:
	//rolls a closed die, "sides" sides, numbered (low) to (low+sides-1)
private int rollDie(){return rand(sides)+low;}

//rolls an open die
private int rollDieOpen(){
face=total=rollDie();
while(face>=high){total+=(face=rollDie());}
return total;
}

//returns a random number, 0 to max-1
private int rand(int max){return (randy.nextInt()&mask)%max;}

Unfortunately, I do not know how slow the pseudorandomizer is, so I don't know how much avoiding it would help. I was considering pregenerating a lookup table that I could reference with a single random number, instead of multiple random numbers like 2d6*-2d6* simulation requires... but the table would be huge to be accurate. A table covering 99.999% of rolls would need 100,000 bytes, which would hurt Cache performance. Alternately, storing the probability table you provided and looking up the value would require minimum n(log(n)) steps to look up a roll from a probability.

A single formula, in this form:

code:
int convertTo2d6roll(double probability){
return something;
}

...assuming the code was fairly short...

...would speed up things a lot.

Of course, the ultimate distribution would still be entirely dependant on Java's pseudorandomizer

However, from examining what you wrote below, which I do not very much understand (but I think I should if I remembered my stats class)... it looks like it has a lot of expensive double-precision floating point division.

Regardless of speed, I would love to see code that implements it, if you have time! And I'll try to figure out what you wrote below, tomorrow=)

-Cherry

P.S. To post code on these forums: Use ["code"] blah blah ["/code"] format. Without the quotes
__________________
Cherry
Reply With Quote
  #6  
Old January 1st, 2004, 04:34 PM
Whismerhill's Avatar

Whismerhill Whismerhill is offline
Corporal
 
Join Date: Nov 2003
Posts: 70
Thanks: 0
Thanked 0 Times in 0 Posts
Whismerhill is on a distinguished road
Default Re: Dominions Dice Roll Chart

>>>>haven't understood the smallest part of alexi code
Reply With Quote
  #7  
Old January 1st, 2004, 04:54 PM

alexti alexti is offline
First Lieutenant
 
Join Date: Dec 2003
Location: Calgary, Canada
Posts: 762
Thanks: 0
Thanked 0 Times in 0 Posts
alexti is on a distinguished road
Default Re: Dominions Dice Roll Chart

Here's my original code:
code:
namespace math {
inline double sum1toInfOf_q_power_n(double q)
{
double c = 1/(1-q);
return c;
}

inline double sum1toInfOf_nq_power_n(double q)
{
double c = q/(1-q);
return c/(1-q);
}

inline double sum1toInfOf_nnq_power_n(double q)
{
return q*(1+q)/pow(1-q,3);
}
}


namespace illwinter_dice {
namespace probability {

// probability that roll of pair of dices is equal <n>
inline double d2rollIsN(long n)
{
long u = (n-1)/5;
long v = n - 5*u;
return pow(q,u+1)*((v-1)*(u+1)*q + (6-v)*u);
}

// probability that roll of 1 pair of dices is greater than the roll
// of another pair of dices at least by <n>
double d2rollIsGreaterThanD2Roll2byAtLeastN(long n)
{
long u = (n-1)/5;
long v = n - 5*u;
double qu2 = pow(q,u+2);
static double c0q2 = math::sum1toInfOf_q_power_n(q*q);
static double c1q2 = math::sum1toInfOf_nq_power_n(q*q);
static double c2q2 = math::sum1toInfOf_nnq_power_n(q*q);
double total = 0;
for (long s = 1; s <= 5; s++)
{
// uu and vv are such that 5uu+vv = 5u+s+v, and 0<=uu and 1<=vv<=5
double uu = u, vv = s+v;
if (s+v > 5)
{
uu++;
vv -= 5;
}

// Calculate coefficients
double a1, a2, b1, b2;
a1 = 6.0 - s*(1-q) - q;
a2 = q*(s-1);

b1 = 20.0 - 5.0*(vv-1)*(14-vv)/12.0;
b2 = b1*uu + 6.0 - (vv-1)*(vv-2)/12.0;

double x = qu2*(c2q2*a1*b1 + c1q2*(a1*b2+a2*b1) + c0q2*a2*b2);
if (s+v > 5)
x = x*q;
total += x;
}
return total;
}

}}

If you're figting for performance, you can use the following code
code:
template <int ROLL2_CACHE_LIMIT, int ROLL2_COMPARE_CACHE_LIMIT>
class CachedDiceProbability {
public:
CachedDiceProbability() { init(); }

inline double d2rollIsN(long n) const
{
assert(n>=0);
if (n > ROLL2_CACHE_LIMIT)
return illwinter_dice:obability::d2rollIsN(n);
return Cache.d2roll[n];
}
inline double d2rollIsGreaterThanD2Roll2byAtLeastN(long n) const
{
assert(n>=0);
if (n > ROLL2_COMPARE_CACHE_LIMIT)
return illwinter_dice:obability::d2rollIsGreaterThanD2 Roll2byAtLeastN(n);
return Cache.d2rollIsGreaterThanD2Roll2[n];
}

protected:
struct {
double d2roll[ROLL2_CACHE_LIMIT+1];
double d2rollIsGreaterThanD2Roll2[ROLL2_COMPARE_CACHE_LIMIT+1];
} Cache;

void init()
{
long i;
Cache.d2roll[0] = 0;
for (i = 1; i <= ROLL2_CACHE_LIMIT; i++)
Cache.d2roll[i] = illwinter_dice:obability::d2rollIsN(i);
for (i = 0; i <= ROLL2_COMPARE_CACHE_LIMIT; i++)
Cache.d2rollIsGreaterThanD2Roll2[i]
= illwinter_dice:obability::d2rollIsGreaterThanD2 Roll2byAtLeastN(i);
}
};

With 50,50 parameters this Cache will cover about 99.9999% of cases and revert to the actual calculations if you need to calculate for the roll (or difference) greater than 50. And it won't take much space either, only 800 bytes.

The root of performance issue is in simulation nature, meaning that you recalculate the same combat thousands of times to get ides of probabilities of outcome. To accelerate things it would be necessary to replace iterative process with analytic formulas. It's not that hard to make an analytic formula in particular cases, but there're so many different situations and analysing all of them is probably too much work.

I have few ideas to increase performance within the same framework though.

Replacing your current code with the my analytic formulas is not likely to produce much gain in general, but you could win some time on the checks (for example, to verify if you can roll required MR check you'd look into the Cached table and see that if you need to have 2 more than opponents, your probability of success is 0.376093, so you'd need to call RNG only once (for range 0..1) and compare result to 0.376093).

For quantative characteristics, like damage roll I would go with caching too (the same idea you suggested). I'm not sure why you're concerned about 100K Cache, is it something Java specific?
In C it would be just direct memory addressing which provides optimal performance and 100K isn't too much to worry about.

I have no idea how fast RNG in Java is, but there're pretty good and fast RNG algorithms. For example:
ftp://random.mat.sbg.ac.at/pub/data/tt800.c
http://www.math.keio.ac.jp/~matumoto...mt19937ar.html

In general I don't know Java much, but I believe it's in general slow at number crunching because of pseudo-code (unless Java optimizer correctly guesses that it needs to compile your code into a native instructions). Otherwise, if you could split interface part from the battle engine and translate engine in C/C++ you'd probably get significant performance boost. But again it would produce extra difficulties with passing data back and forth.
Reply With Quote
  #8  
Old January 14th, 2004, 07:55 PM
Saber Cherry's Avatar

Saber Cherry Saber Cherry is offline
Major General
 
Join Date: Oct 2003
Location: Crystal Tokyo
Posts: 2,453
Thanks: 0
Thanked 0 Times in 0 Posts
Saber Cherry is on a distinguished road
Default Re: Dominions Dice Roll Chart

Mind Duel Death Rates.

Differential Rolls for Opposing 1d6 Closed:

-6 : 0.000%
-5 : 2.788%
-4 : 5.539%
-3 : 8.342%
-2 : 11.119%
-1 : 13.866%
0 : 16.628%
1 : 13.862%
2 : 11.131%
3 : 8.323%
4 : 5.595%
5 : 2.807%
6 : 0.000%

Cumulative Death Probability:

-6 :100.000%
-5 :100.000%
-4 : 97.212%
-3 : 91.673%
-2 : 83.331%
-1 : 72.212%
0 : 58.346%
1 : 41.718%
2 : 27.856%
3 : 16.725%
4 : 8.402%
5 : 2.807%
6 : 0.000%

The minor asymmetry is due to small sampling size (2,000,000) so it seems to be good to 2.5 figures.

Those are rolls for opposing 1d6. The "Cumulative" figures give a mages chance of death in a mind duel with the listed skill (ignore the plus signs). In other words, if a mage's skill is 5 lower, he always dies; 4 lower, he dies 97.2% of the time... at equal levels, each mage has a 58.3% chance of death. +5 gives you a 100% chance of killing the opponent (but you still die 2.8% of the time) and you have to be 6 levels above or higher to always win and never die.

Note that communion-induced magic levels are not displayed on the screen.

-Cherry

P.S. Alexti: Thanks for codifying your algorithm! I have not translated it to Java yet (laziness) but I probably will soon=)
__________________
Cherry
Reply With Quote
  #9  
Old January 24th, 2004, 07:34 PM
Saber Cherry's Avatar

Saber Cherry Saber Cherry is offline
Major General
 
Join Date: Oct 2003
Location: Crystal Tokyo
Posts: 2,453
Thanks: 0
Thanked 0 Times in 0 Posts
Saber Cherry is on a distinguished road
Default Re: Dominions Dice Roll Chart

Damage Statistics. This chart shows the average damage done for a successful hit, with this difference between attacker's strength+damage and defender's protection. In other words, row "-7" will show the average damage by a light infantry (strength 10, spear damage 3) against a Black Plate Ulm infantry (protection 20), assuming a successful hit.

Obviously, this does not take into account the fact that high fatigue levels give a chance of armor-piercing attacks.

Testing (2d6*, labelled 0-5, offset=2) over 40000000 rolls.

Average hit damage for this (strength+damage)-protection value:

-30: 0.000
-29: 0.000
-28: 0.000
-27: 0.001
-26: 0.001
-25: 0.001
-24: 0.002
-23: 0.002
-22: 0.003
-21: 0.004
-20: 0.006
-19: 0.008
-18: 0.011
-17: 0.015
-16: 0.020
-15: 0.028
-14: 0.038
-13: 0.052
-12: 0.071
-11: 0.097
-10: 0.131
-9: 0.177
-8: 0.239
-7: 0.321
-6: 0.429
-5: 0.570
-4: 0.754
-3: 0.991
-2: 1.29
-1: 1.67
0: 2.13
1: 2.67
2: 3.29
3: 3.99
4: 4.75
5: 5.57
6: 6.43
7: 7.32
8: 8.24
9: 9.18
10: 10.13
11: 11.10
12: 12.07
13: 13.05
14: 14.04
15: 15.03
16: 16.02
17: 17.02
18: 18.01
19: 19.01
20: 20.00


Everything over 20 is essentially equal to the difference.

-Cherry
__________________
Cherry
Reply With Quote
Reply

Bookmarks


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On

Forum Jump


All times are GMT -4. The time now is 09:27 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Copyright ©1999 - 2025, Shrapnel Games, Inc. - All Rights Reserved.