Switch Theme:

May, or may not, have gotten bored at work....  [RSS] Share on facebook Share on Twitter Submit to Reddit
»
Author Message
Advert


Forum adverts like this one are shown to any user who is not logged in. Join us by filling out a tiny 3 field form and you will get your own, free, dakka user account which gives a good range of benefits to you:
  • No adverts like this in the forums anymore.
  • Times and dates in your local timezone.
  • Full tracking of what you have read so you can skip to your first unread post, easily see what has changed since you last logged in, and easily see what is new at a glance.
  • Email notifications for threads you want to watch closely.
  • Being a part of the oldest wargaming community on the net.
If you are already a member then feel free to login now.




Made in us
Regular Dakkanaut





So I got bored at work and realized I haven't found any sort of testing app that I like for 40k. Then I got to thinking more: I have yet to see a true large sample statistical unit-to-unit analysis done for any armies to determine which on all in all is the "most reliable". So.... I started programming it. Right now I am laying the framework for it but when all is said and done I am going to have the program do a cycle of 10k test rolls of hits up through wounds dealt for each unit up against each toughness in the game and push the results to a database for analysis.

My IT job can get really fracking boring...
[Thumb - programming.PNG]
My rundown


WAR IS ALL WE KNOW
In the grim darkness of the far future, there is only Brussels Sprouts.

 
   
Made in no
Grisly Ghost Ark Driver





Looking at distribution of hits/wounds/damage might be interesting too
   
Made in us
Regular Dakkanaut





torblind wrote:
Looking at distribution of hits/wounds/damage might be interesting too


That's what I am wanting to do. If I don't crash my computer running that size sample I additionally want to see how many out of a thousand wounds each unit will save at each toughness, etc etc etc. It's not horribly difficult to program it all just really time consuming.

WAR IS ALL WE KNOW
In the grim darkness of the far future, there is only Brussels Sprouts.

 
   
Made in gb
Lord of the Fleet






Why the many iterations? You can derive the distributions directly.

All the iterations are going to do is show up any biases in your RNG.
   
Made in fr
Longtime Dakkanaut




I didn't understand exactly what you want to do, but as others have said, you can solve this analytically.

A single hit/wound/save sequence is an event with two outcomes (fail or success), and the probability of that event is just the product of the probability of each roll. The probability is everything you need to fully describe it here; it's what's often called a Bernouilli test.
Then if you want to look at what happens when you have multiple such events (for instance multiple models from the same units shooting), you need to "sum" your basic events. The sum of Bernouilli trials gives you a binomial distribution.

In any case, even if you wanted to solve this numerically, I think a combinatory approach would be better, as it would give you exact results. If you have random numbers of hits, random damage, and FNP rolls, it might create too many outcomes to get the complete tree, but there are ways to "aggregate" some parts of the tree to still be able to solve this fully.

Otherwise you can keep running many trials, and use the analytical result to test your program
   
Made in no
Grisly Ghost Ark Driver





fresus wrote:
I didn't understand exactly what you want to do, but as others have said, you can solve this analytically.

A single hit/wound/save sequence is an event with two outcomes (fail or success), and the probability of that event is just the product of the probability of each roll. The probability is everything you need to fully describe it here; it's what's often called a Bernouilli test.
Then if you want to look at what happens when you have multiple such events (for instance multiple models from the same units shooting), you need to "sum" your basic events. The sum of Bernouilli trials gives you a binomial distribution.

In any case, even if you wanted to solve this numerically, I think a combinatory approach would be better, as it would give you exact results. If you have random numbers of hits, random damage, and FNP rolls, it might create too many outcomes to get the complete tree, but there are ways to "aggregate" some parts of the tree to still be able to solve this fully.

Otherwise you can keep running many trials, and use the analytical result to test your program


One problem comes in the form of variable damage.

Suppose my 3x6 destroyers all hit and wound with their rolls, I now have 54 D3 rolls to make for damage, or the sum of 54 uniform distributions, which is quite the analytical challenge. To make it more interesting, each of which has a 5+++ FNP roll


Automatically Appended Next Post:
And you could throw in a heavy destroyer there with heavy D6 damage in the same unit just to mix things up.

This message was edited 1 time. Last update was at 2018/06/01 08:19:12


 
   
Made in fr
Longtime Dakkanaut




torblind wrote:
One problem comes in the form of variable damage.

Suppose my 3x6 destroyers all hit and wound with their rolls, I now have 54 D3 rolls to make for damage, or the sum of 54 uniform distributions, which is quite the analytical challenge. To make it more interesting, each of which has a 5+++ FNP roll

It does make it a bit more difficult and tedious, but can still be solved analytically.
In your example, you have 54 independent D3 rolls, each followed by a FNP roll. So for each damage roll, you can cause 3 damages (roll a 3, then fail all FNPs), or 2 (roll a 3 and save one, or roll a 2 and save none), or 1, or 0. It's pretty easy to get the probabilities p0, p1, p2, and p3 to cause 0, 1, 2, or 3 damage for a given wounding hit.
Now, to get the probability of causing N damages with 54 wounding hits (N has to be lower than 54 * 3 obviously), you can just expand the polynome (p0 + p1 * x + p2 * x2 + p3 * x3)^54 . The coefficient in front of x^N will be the probability to get exactly N damages.

So yes, random number of hits and/or damages make the whole thing tedious. It's not a simple binomial distribution anymore, and it's probably best to use some appropriate statistical software to calculate all the coefficients to get means, variances, or plot the distributions, but it's still possible to solve it analytically.
I understand it's sometimes simpler to just try and do many trials (and increase the number of trials until you get consistent results), especially since it doesn't require that much computational time. Additionally, some people posses the programming background to do it, but might not have the statistical background to go the full-analytical route. But the OP seems to want to develop a better solution than the existing ones, and in my opinion the "statistical" approach is the best one, as it gives exact results.
   
Made in no
Grisly Ghost Ark Driver





fresus wrote:
torblind wrote:
One problem comes in the form of variable damage.

Suppose my 3x6 destroyers all hit and wound with their rolls, I now have 54 D3 rolls to make for damage, or the sum of 54 uniform distributions, which is quite the analytical challenge. To make it more interesting, each of which has a 5+++ FNP roll

It does make it a bit more difficult and tedious, but can still be solved analytically.
In your example, you have 54 independent D3 rolls, each followed by a FNP roll. So for each damage roll, you can cause 3 damages (roll a 3, then fail all FNPs), or 2 (roll a 3 and save one, or roll a 2 and save none), or 1, or 0. It's pretty easy to get the probabilities p0, p1, p2, and p3 to cause 0, 1, 2, or 3 damage for a given wounding hit.
Now, to get the probability of causing N damages with 54 wounding hits (N has to be lower than 54 * 3 obviously), you can just expand the polynome (p0 + p1 * x + p2 * x2 + p3 * x3)^54 . The coefficient in front of x^N will be the probability to get exactly N damages.

So yes, random number of hits and/or damages make the whole thing tedious. It's not a simple binomial distribution anymore, and it's probably best to use some appropriate statistical software to calculate all the coefficients to get means, variances, or plot the distributions, but it's still possible to solve it analytically.
I understand it's sometimes simpler to just try and do many trials (and increase the number of trials until you get consistent results), especially since it doesn't require that much computational time. Additionally, some people posses the programming background to do it, but might not have the statistical background to go the full-analytical route. But the OP seems to want to develop a better solution than the existing ones, and in my opinion the "statistical" approach is the best one, as it gives exact results.


.. Now throw Quantum Shelding into the frey and sit back and enjoy the meltdown.


It all depends on what response you need.

To simply stuff things into a DB its a one off thing. Though the additional variability in terms of the jungle of unit options makes it unlikely to work for your exact case. (He showed off tesla only, there could be 15+ other options applicable)

I'm continously improving a web interface for this kind of analysis, boldly linked to in my signature, that runs client side (ie javascript), and my plan is to strike the balance between exact and simulated results.

For the everyday game the simulated precision will likely do. if your 95% damage interval is 2-8 or 1.8-7.7 probably doesnt matter much.

But I hope to be able to isolate the variable bits (variable damage, variable number of hits), analyze those and consider if simulation is necessary, and analytically calculate the rest.
   
Made in gb
Lord of the Fleet






Fields of blood already have a tool that produces the distribution for one profile against another.

OP is taking about aggregating results for many weapons and units. That's interesting.

I think he could save himself a bunch of hassle by simply aggregating results from FoB rather than doing his 10K simulated passes.
   
Made in us
Regular Dakkanaut





Let me start with I love how absolutely geeky this thread has already got and I love this community lol.

This is more of a programming exercise than anything for me and just something to kick around for giggles. The reason for the printouts of the dice total in the picture are just so I can have a visual representation in the console with a printout to make sure it's doing what I want.

torblind wrote:
fresus wrote:


To simply stuff things into a DB its a one off thing. Though the additional variability in terms of the jungle of unit options makes it unlikely to work for your exact case. (He showed off tesla only, there could be 15+ other options applicable)

I'm continously improving a web interface for this kind of analysis, boldly linked to in my signature, that runs client side (ie javascript), and my plan is to strike the balance between exact and simulated results.

For the everyday game the simulated precision will likely do. if your 95% damage interval is 2-8 or 1.8-7.7 probably doesnt matter much.


Tesla is the only option right now as it's all I've had time to mess with. I only have about two hours tops into the whole thing and right now it's a single python script. I will be splitting it in to multiple scripts down the line and writing a main controller script that calls for each army's individual script. Right now all this is is a proof of concept and laying the very basic framework.

The reason for the database is to store the outcomes for late manipulation. Essentially I will have the SQLDB laid out as "Name, amount of attacks, amount of hits, hit percentage, successful number of wounds at each level".

torblind wrote:

One problem comes in the form of variable damage.

Suppose my 3x6 destroyers all hit and wound with their rolls, I now have 54 D3 rolls to make for damage, or the sum of 54 uniform distributions, which is quite the analytical challenge. To make it more interesting, each of which has a 5+++ FNP roll



And you could throw in a heavy destroyer there with heavy D6 damage in the same unit just to mix things up.


Not really that much of a problem. The hierarchy for the script as it sits is amount of d6 rolled, how many hit based on BS, how many successful wound rolls based on toughness (about to be in it). All you would need is another function specific to the model being rolled for that says something like (in pseudo code of course as I have not had coffee yet)

if destroyerModel == True:
damageRoll = For wound in wound[Random(1,4)]


 Scott-S6 wrote:
Fields of blood already have a tool that produces the distribution for one profile against another.

OP is taking about aggregating results for many weapons and units. That's interesting.

I think he could save himself a bunch of hassle by simply aggregating results from FoB rather than doing his 10K simulated passes.


Not familiar with FoB but I'll look into it. It's not really that much of a hassle as I am not doing it as some end all be all thing and just for fun in free time. It has more to do with just being a programming exercise and a portfolio piece for GitHub and a tool if anyone wanted to mess with it.


This message was edited 1 time. Last update was at 2018/06/01 13:15:40


WAR IS ALL WE KNOW
In the grim darkness of the far future, there is only Brussels Sprouts.

 
   
Made in no
Grisly Ghost Ark Driver





 Nydhog wrote:


Not really that much of a problem. The hierarchy for the script as it sits is amount of d6 rolled, how many hit based on BS, how many successful wound rolls based on toughness (about to be in it). All you would need is another function specific to the model being rolled for that says something like (in pseudo code of course as I have not had coffee yet)

if destroyerModel == True:
damageRoll = For wound in wound[Random(1,4)]




I was commenting on the analytical solution, not the simulation process. The problem for the simluation will be to know when the simulation has run long enough.


Automatically Appended Next Post:
Something that would be nice for you (I presume), would be to load unit definitions from *all* the battlescribe data files, with a subset of relevant options (or just all!), and then run the simulations based off of those.


Automatically Appended Next Post:
Here's the link: https://github.com/BSData/wh40k

This message was edited 2 times. Last update was at 2018/06/01 13:21:43


 
   
Made in us
Regular Dakkanaut





torblind wrote:
 Nydhog wrote:


Not really that much of a problem. The hierarchy for the script as it sits is amount of d6 rolled, how many hit based on BS, how many successful wound rolls based on toughness (about to be in it). All you would need is another function specific to the model being rolled for that says something like (in pseudo code of course as I have not had coffee yet)

if destroyerModel == True:
damageRoll = For wound in wound[Random(1,4)]




I was commenting on the analytical solution, not the simulation process. The problem for the simluation will be to know when the simulation has run long enough.


Automatically Appended Next Post:
Something that would be nice for you (I presume), would be to load unit definitions from *all* the battlescribe data files, with a subset of relevant options (or just all!), and then run the simulations based off of those.


Automatically Appended Next Post:
Here's the link: https://github.com/BSData/wh40k


Bless you, sir. Bless you.

WAR IS ALL WE KNOW
In the grim darkness of the far future, there is only Brussels Sprouts.

 
   
Made in gb
Longtime Dakkanaut




Sounds an interesting project, I do Monte-Carlo simulations as part of my job, spitting out 20GB data files is not uncommon and thats using Visual Basic.

what are you coding this in?

to be honest the "rules" are pretty simple so shouldn't be too hard to do the actual simulation, its the analysis on the dataset after thats the interesting bit
   
Made in us
Dakka Veteran




How is this different than standard mathhammer?

The only additional functionality I'm seeing in this is that you're "rolling" dice; which while cool - doesn't matter.

If your code is properly randomized, it's no different than mathhammering it; as you'll get similar enough results. [*] If your code ISN'T properly randomized, then you're just getting biased, false, information - which is to say, useless.

If the intent is to build a dice rolling app, then filter the rolls through a 40k calculation interface; well, that's an entirely different endgoal - rock on.

[*]=Yes, dice have streaks; you can roll all 6's, all 1's, and everything in between; but at the end of the day, it CAN'T add anything, because it's either biased, or it's not - math is the only real way to calculate results.

This message was edited 3 times. Last update was at 2018/06/01 21:59:52


 
   
Made in us
Regular Dakkanaut





leopard wrote:Sounds an interesting project, I do Monte-Carlo simulations as part of my job, spitting out 20GB data files is not uncommon and thats using Visual Basic.

what are you coding this in?

to be honest the "rules" are pretty simple so shouldn't be too hard to do the actual simulation, its the analysis on the dataset after thats the interesting bit


Python.



fe40k wrote:How is this different than standard mathhammer?

The only additional functionality I'm seeing in this is that you're "rolling" dice; which while cool - doesn't matter.

If your code is properly randomized, it's no different than mathhammering it; as you'll get similar enough results. [*] If your code ISN'T properly randomized, then you're just getting biased, false, information - which is to say, useless.

If the intent is to build a dice rolling app, then filter the rolls through a 40k calculation interface; well, that's an entirely different endgoal - rock on.

[*]=Yes, dice have streaks; you can roll all 6's, all 1's, and everything in between; but at the end of the day, it CAN'T add anything, because it's either biased, or it's not - math is the only real way to calculate results.


I'm not trying to reinvent the wheel. I am just trying to write a program for fun to use for my own amusement and to post as a GitHub project in my portfolio since it's more complex than your standard import csv, scrub it, analyze it, output a graph. Think of it as a coding exercise and as me honing my programming skills because that's essentially what it is. The only major difference is my goal is to have it automatically cycle through each toughness value based on the initial wound roll to say "You inflicted this many wounds against toughness <toughness>".


WAR IS ALL WE KNOW
In the grim darkness of the far future, there is only Brussels Sprouts.

 
   
Made in gb
Longtime Dakkanaut




not played all that much with Python, will be at some point though

and seriously +lots to writing stuff because you can and as a learning exercise

good luck with it
   
Made in us
Regular Dakkanaut





leopard wrote:
not played all that much with Python, will be at some point though

and seriously +lots to writing stuff because you can and as a learning exercise

good luck with it


Python is REALLY simple once you get used to the forced syntax, but can be really tricky at times if that makes sense. It's like a simplified C# but with that comes some headache.

As an example of how it reads the code right now for the shooting round to see hits is this:



The reason for randrange(1,7) being how it is is Python stops counting AT the number you post, so 1-6 is actually written 1-7. The way that this is written means I can pass any unit into it right off the bat because they are stored like this in an "units.py" file.



When the main app.py file calls for the variable "triggerName" and it gets that it wants "necronimmortal" it assigns all the other variables as needed.

I am still working out the wound rolls code and haven't had much time to do so since I am working two jobs and in programming school as well. Between that and it being renfaire season here and me being a blacksmith it's SUPER hectic.

WAR IS ALL WE KNOW
In the grim darkness of the far future, there is only Brussels Sprouts.

 
   
Made in no
Grisly Ghost Ark Driver





Blacksmith?
   
Made in fr
Longtime Dakkanaut




Always nice to see someone enjoy coding
If your code is a bit too slow for your liking, you might want to check NumPy. Here you're dealing with big arrays (assuming totalRolls is pretty large), and NumPy is very efficient at handling that.
   
 
Forum Index » 40K General Discussion
Go to: