Results 1 to 14 of 14
  1. - Top - End - #1
    Colossus in the Playground
     
    JNAProductions's Avatar

    Join Date
    Jul 2014
    Location
    Fighting Demons!

    Default 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 Details
    Show
    Their Strength can be 7, 8, or 9, and they have a +1 to-wound. 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 Avatars
    Show
    Spoiler: Avatar (Not In Use) By Professor Gnoll!
    Show


    Spoiler: Avatar (Not In Use) By Cdr. Fallout!
    Show

  2. - Top - End - #2
    Titan in the Playground
    Join Date
    May 2007
    Location
    The Land of Cleves
    Gender
    Male

    Default 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

  3. - Top - End - #3
    Colossus in the Playground
     
    JNAProductions's Avatar

    Join Date
    Jul 2014
    Location
    Fighting Demons!

    Default 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 Avatars
    Show
    Spoiler: Avatar (Not In Use) By Professor Gnoll!
    Show


    Spoiler: Avatar (Not In Use) By Cdr. Fallout!
    Show

  4. - Top - End - #4
    Bugbear in the Playground
     
    Excession's Avatar

    Join Date
    Jun 2008
    Location
    New Zealand
    Gender
    Male

    Default 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 Python-like pseudo-code:

    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)
    I don't know how 40K handles attack resolution, so I can't fill in simulate_attack. Assuming a simple dice roll you could again just go through each possibility and average the results. Displaying a bar graph rather than an average is left as an exercise for the reader.

    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; 2019-04-30 at 08:34 PM.

  5. - Top - End - #5
    Titan in the Playground
     
    Brother Oni's Avatar

    Join Date
    Nov 2007
    Location
    Cippa's River Meadow
    Gender
    Male

    Default Re: Programming For 40k

    Quote Originally Posted by Excession View Post
    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)
    You forgot the burning incense, sacred unguents and chanting by candle light.

  6. - Top - End - #6
    Bugbear in the Playground
     
    Randuir's Avatar

    Join Date
    May 2017
    Gender
    Female

    Default Re: Programming For 40k

    Quote Originally Posted by Brother Oni View Post
    You forgot the burning incense, sacred unguents and chanting by candle light.
    In addition Excession also forgot to import appease_MachineSpirit and PraiseEmperor, so that program is pretty likely to corrupt your computer :P
    Jasnah avatar by Zea Mays

  7. - Top - End - #7
    Titan in the Playground
     
    BlackDragon

    Join Date
    Feb 2007
    Location
    Manchester, UK
    Gender
    Male

    Default Re: Programming For 40k

    Quote Originally Posted by Randuir View Post
    In addition Excession also forgot to import appease_MachineSpirit and PraiseEmperor, so that program is pretty likely to corrupt your computer :P
    Nah, so long as he doesn't directly call invoke_Slaanesh he'll be fine.

  8. - Top - End - #8
    Troll in the Playground
     
    Griffon

    Join Date
    Jun 2013
    Location
    Bristol, UK

    Default Re: Programming For 40k

    Quote Originally Posted by factotum View Post
    Nah, so long as he doesn't directly call invoke_Slaanesh he'll be fine.
    Doesn't all programming inherently invoke that function?
    The end of what Son? The story? There is no end. There's just the point where the storytellers stop talking.

  9. - Top - End - #9
    Ogre in the Playground
     
    Telok's Avatar

    Join Date
    Mar 2005
    Location
    PRAK

    Default Re: Programming For 40k

    Quote Originally Posted by halfeye View Post
    Doesn't all programming inherently invoke that function?
    Only javascript. Most of the others use tzeentchBlackBox.HopeItWorks(main)

    Unless you're using a functional language, COBOL, or FORTRAN. Then it's Khorne for the functionals and usually Nurgle for the other two.
    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.

  10. - Top - End - #10
    Orc in the Playground
     
    WolfInSheepsClothing

    Join Date
    Aug 2018
    Gender
    Intersex

    Default 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).

  11. - Top - End - #11
    Barbarian in the Playground
     
    NecromancerGuy

    Join Date
    Aug 2017

    Default 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...

  12. - Top - End - #12
    Ogre in the Playground
     
    ElfPirate

    Join Date
    Aug 2013

    Default Re: Programming For 40k

    Quote Originally Posted by LordEntrails View Post
    Wouldn't a spreadsheet like excel work? No coding required. Just a few columns and then lots of lookup and stuff...
    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; 2019-05-02 at 05:19 AM.

  13. - Top - End - #13
    Colossus in the Playground
     
    JNAProductions's Avatar

    Join Date
    Jul 2014
    Location
    Fighting Demons!

    Default Re: Programming For 40k

    So, to complete what's needed...

    Spoiler: Psychic
    Show
    Roll 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 Assignment
    Show
    Roll 1d3+6, assign to Strength.
    Roll 1d3, assign to AP.
    Roll 1d3. If equal to 1, reroll once. Assign to Damage.


    Spoiler: Shooting
    Show
    Roll 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 Cacophony
    Show
    To 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; 2019-05-02 at 08:46 AM.
    I have a LOT of Homebrew!

    Current Avatar by Elder Tsofu, who is awesome!

    Spoiler: Former Avatars
    Show
    Spoiler: Avatar (Not In Use) By Professor Gnoll!
    Show


    Spoiler: Avatar (Not In Use) By Cdr. Fallout!
    Show

  14. - Top - End - #14
    Bugbear in the Playground
     
    Randuir's Avatar

    Join Date
    May 2017
    Gender
    Female

    Default Re: Programming For 40k

    Quote Originally Posted by JNAProductions View Post
    So, to complete what's needed...

    Spoiler: Psychic
    Show
    Roll 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 Assignment
    Show
    Roll 1d3+6, assign to Strength.
    Roll 1d3, assign to AP.
    Roll 1d3. If equal to 1, reroll once. Assign to Damage.


    Spoiler: Shooting
    Show
    Roll 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 Cacophony
    Show
    To 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?
    Yeah, I think so. The following piece of python code runs one instance of shooting and prints the damage:
    Spoiler
    Show

    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=11-strength
        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
    Show

    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=11-strength
            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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •