Results 1 to 14 of 14
Thread: Programming For 40k

20190430, 05:49 PM (ISO 8601)
 Join Date
 Jul 2014
 Location
 Fighting Demons!
Programming For 40k
So, I'm trying to figure out how to run a simulation of numbers.
Obliterators, in Warhammer 40,000, have really, REALLY random stats. And I want to run a simulation of them shooting at a target, with the randomness accounted for. To do that requires a LOT of manual effort, since there are 27 different combinations possible for their guns.
Does anyone know a quick and easy way to set this up for someone who doesn't know how to code?
Spoiler: More DetailsTheir Strength can be 7, 8, or 9, and they have a +1 towound. This means that they wound the target (a Repulsor in this case) on a 4+, 3+, or 2+.
Their AP can be 1, 2, or 3, meaning the Repulsor gets a 4+, 5+, or 6+ save.
And their Damage can be 1, 2, or 3.I have a LOT of Homebrew!
Current Avatar by Elder Tsofu, who is awesome!
Spoiler: Former AvatarsSpoiler: Avatar (Not In Use) By Professor Gnoll!
Spoiler: Avatar (Not In Use) By Cdr. Fallout!

20190430, 08:20 PM (ISO 8601)
 Join Date
 May 2007
 Location
 The Land of Cleves
 Gender
Re: Programming For 40k
You want to go Monte Carlo. For each one, choose random values of each stat, and then calculate whether that one hit and how much damage it does. And then repeat a whole bunch of times. Don't worry about manually covering every possible combination; let the random number generator take care of that.
Time travels in divers paces with divers persons.
—As You Like It, III:ii:328
Chronos's Unalliterative Skillmonkey Guide
Current Homebrew: Blood Warrior Shadow Rider

20190430, 08:28 PM (ISO 8601)
 Join Date
 Jul 2014
 Location
 Fighting Demons!
Re: Programming For 40k
Right. How do I do that?
I have a LOT of Homebrew!
Current Avatar by Elder Tsofu, who is awesome!
Spoiler: Former AvatarsSpoiler: Avatar (Not In Use) By Professor Gnoll!
Spoiler: Avatar (Not In Use) By Cdr. Fallout!

20190430, 08:31 PM (ISO 8601)
 Join Date
 Jun 2008
 Location
 New Zealand
 Gender
Re: Programming For 40k
Monte Carlo seems a bit much for only 27 combinations. It should be reasonable to just calculate every outcome. A bit of Pythonlike pseudocode:
Code:total = 0 count = 0 for strength in 7, 8, 9: for ap in 1, 2, 3: for damage in 1, 2, 3: total += simulate_attack(strength, ap, damage) count += 1 print('Average:', total / count)
This assume that each value of those three variables is equally likely. If not you would need to calculate a weighted average instead.Last edited by Excession; 20190430 at 08:34 PM.

20190501, 06:45 AM (ISO 8601)
 Join Date
 Nov 2007
 Location
 Cippa's River Meadow
 Gender

20190501, 08:51 AM (ISO 8601)
 Join Date
 May 2017
 Gender
Re: Programming For 40k
Jasnah avatar by Zea Mays

20190501, 10:03 AM (ISO 8601)
 Join Date
 Feb 2007
 Location
 Manchester, UK
 Gender

20190501, 10:05 AM (ISO 8601)
 Join Date
 Jun 2013
 Location
 Bristol, UK

20190501, 10:27 AM (ISO 8601)
 Join Date
 Mar 2005
 Location
 PRAK
Re: Programming For 40k
Niven's Laws, #5
If you've nothing to say, say it any way you like. Stylistic innovations, contorted story lines or none, exotic or genderless pronouns, internal inconsistencies, the recipe for preparing your lover as a cannibal banquet: feel free. If what you have to say is important and/or difficult to follow, use the simplest language possible. If the reader doesn't get it then, let it not be your fault.

20190501, 11:09 AM (ISO 8601)
 Join Date
 Aug 2018
 Gender
Re: Programming For 40k
Brute force and determination. And a little cheating.
Okay, step one is either a 3/6, 4/6 or 5/6 chance to wound, evenly distributed. So it's a 4/6, or 2/3, chance, because that's how averages work.
Step two is either a 3/6, 4/6 or 5/6 chance that the reppy fails its save. Again, that means it's a 2/3 chance for the same reason.
Finally, step 3 is an average of 2 wounds.
The chance that you wound is therefore 4/9, so you can expect to do 8/9 of a wound per shot. Alternatively, there's a 4/27 chance each of 1, 2, or 3 wounds, and therefore a 15/27=5/9 chance of no wounds (which you can also work out from the 4/9 chance that you will wound).

20190502, 12:16 AM (ISO 8601)
 Join Date
 Aug 2017
Re: Programming For 40k
Wouldn't a spreadsheet like excel work? No coding required. Just a few columns and then lots of lookup and stuff...

20190502, 05:16 AM (ISO 8601)
 Join Date
 Aug 2013
Re: Programming For 40k
Yes.
But that requires sacrifices to all the known* Chaos Gods.
*and a couple of unknown ones
And for the record, using either appease_MachineSpirit or PraiseEmperor in conjuction with Obliterators immediately triggers the doExterminatus.Inquisitor(random_value) error and there's just no way to trap or handle that.Last edited by snowblizz; 20190502 at 05:19 AM.

20190502, 08:45 AM (ISO 8601)
 Join Date
 Jul 2014
 Location
 Fighting Demons!
Re: Programming For 40k
So, to complete what's needed...
Spoiler: PsychicRoll 2d6. If equal to or greater than 7, assign "Yes" to "Reroll 1s" and move to next step. If less than 7, reroll the lower die once. If equal to or less than 6 after reroll, assign "No" to "Reroll 1s".
Roll 2d6, If equal to or greater than 6, assign "Yes" to "+1 Hit" and move on to next step. If less than 6, reroll the lower die once, but only if no reroll was used in the first step. If equal to or less than 5 after reroll, assign "No" to "+1 Hit".
Spoiler: Stat AssignmentRoll 1d3+6, assign to Strength.
Roll 1d3, assign to AP.
Roll 1d3. If equal to 1, reroll once. Assign to Damage.
Spoiler: ShootingRoll 1d6. If equal to or greater than 3, hit and move to next step. If equal to 1, reroll once, if "Reroll 1s" is "Yes". Add +1 to the roll if "+1 Hit" is "Yes".
Roll 1d6. If Strength equals 7, move on to next step on equal to or greater than 4. If Strength equals 8, move on to the next step on equal to or greater than 3. If Strength equals 9, move on to the next step on equal to or greater than 2. If equal to 1 (regardless of what Strength is), reroll once, if "Reroll 1s" is "Yes".
Roll 1d6. If AP equals 1, move on to the next step if equal to or less than 3. If AP equals 2, move on to the next step if equal to or less than 4. If AP equals 3, move on to the next step if equal to or less than 5.
Assign damage, equal to the Damage value. Once total damage equals 18, stop.
Repeat the entirety of the shooting up to 18 times or whenever damage dealt reaches 18, whichever comes first.
Record total damage dealt.
Spoiler: Endless CacophonyTo do Endless Cacophony, repeat Stat Assignment, but only reroll 1 on Damage if a reroll has not already been used on Damage.
Then, repeat Shooting. If total damage was less than 18, add to existing total and stop at 18. If total damage was 18, repeat shooting with a new total.
Add the two totals together, if there are two totals, to record final damage dealt.
Does this make it clearer how to do it?Last edited by JNAProductions; 20190502 at 08:46 AM.
I have a LOT of Homebrew!
Current Avatar by Elder Tsofu, who is awesome!
Spoiler: Former AvatarsSpoiler: Avatar (Not In Use) By Professor Gnoll!
Spoiler: Avatar (Not In Use) By Cdr. Fallout!

20190503, 07:04 AM (ISO 8601)
 Join Date
 May 2017
 Gender
Re: Programming For 40k
Yeah, I think so. The following piece of python code runs one instance of shooting and prints the damage:
Spoiler
Code:from random import * """ import Praise_Emperor import appease_MachineSpirit """ """ psychic """ #rerolls psy1_a=randint(1,6) psy1_b=randint(1,6) if psy1_a+psy1_b<7: use_psy_reroll=1 if psy1_a<psy1_b: psy1_a=randint(1,6) else: psy1_b=randint(1,6) if psy1_a+psy1_b>=7: reroll1=1 else: reroll1=0 else: use_psy_reroll=0 reroll1=1 #+1 to hit psy2_a=randint(1,6) psy2_b=randint(1,6) if psy2_a+psy2_b<6 and use_psy_reroll==0: use_psy_reroll=1 if psy2_a<psy2_b: psy2_a=randint(1,6) else: psy2_b=randint(1,6) if psy2_a+psy2_b<6: bonus_tohit=0 else: bonus_tohit=1 elif psy2_a+psy2_b>6: bonus_tohit=1 else: bonus_tohit=0 """ stats """ endless=0 use_damage_reroll=0 damage_count=0 damage_count_save=0 while endless<2: strength=randint(1,3)+6 AP=randint(1,3) damage=randint(1,3) if damage==1 and use_damage_reroll==0: damage=randint(1,3) use_damage_reroll=1 strength_target=11strength AP_target=2+AP """ shooting """ shot_count=0 while damage_count<18 and shot_count<18: #hitting tohit=randint(1,6) if tohit==1 and reroll1==1: tohit=randint(1,6) if tohit+bonus_tohit>=3: #wounding wound=randint(1,6) if wound==1 and reroll1==1: wound=randint(1,6) if wound>=strength_target: #armor_piercing pierce=randint(1,6) if pierce>=AP_target: damage_count+=damage shot_count+=1 if damage_count>=18: damage_count_save=damage_count damage_count=0 endless+=1 print damage_count+damage_count_save
if you're looking for average damage over long periods of time, use something like this instead:
Spoiler
Code:from random import * """ import Praise_Emperor import appease_MachineSpirit """ run=0 damage_total=0 while run<10000: run+=1 """ psychic """ #rerolls psy1_a=randint(1,6) psy1_b=randint(1,6) if psy1_a+psy1_b<7: use_psy_reroll=1 if psy1_a<psy1_b: psy1_a=randint(1,6) else: psy1_b=randint(1,6) if psy1_a+psy1_b>=7: reroll1=1 else: reroll1=0 else: use_psy_reroll=0 reroll1=1 #+1 to hit psy2_a=randint(1,6) psy2_b=randint(1,6) if psy2_a+psy2_b<6 and use_psy_reroll==0: use_psy_reroll=1 if psy2_a<psy2_b: psy2_a=randint(1,6) else: psy2_b=randint(1,6) if psy2_a+psy2_b<6: bonus_tohit=0 else: bonus_tohit=1 elif psy2_a+psy2_b>6: bonus_tohit=1 else: bonus_tohit=0 """ stats """ endless=0 use_damage_reroll=0 damage_count=0 damage_count_save=0 while endless<2: strength=randint(1,3)+6 AP=randint(1,3) damage=randint(1,3) if damage==1 and use_damage_reroll==0: damage=randint(1,3) use_damage_reroll=1 strength_target=11strength AP_target=2+AP """ shooting """ shot_count=0 while damage_count<18 and shot_count<18: #hitting tohit=randint(1,6) if tohit==1 and reroll1==1: tohit=randint(1,6) if tohit+bonus_tohit>=3: #wounding wound=randint(1,6) if wound==1 and reroll1==1: wound=randint(1,6) if wound>=strength_target: #armor_piercing pierce=randint(1,6) if pierce>=AP_target: damage_count+=damage shot_count+=1 if damage_count>=18: damage_count_save=damage_count damage_count=0 endless+=1 damage_total+=damage_count+damage_count_save print "average damage is ",damage_total/10000.
Jasnah avatar by Zea Mays