Python
import random
import numpy as np
import matplotlib.pyplot as plt

def calc_damage_dealt(n_dice, hit_threshold, damage_per_dice):
    total_damage = 0
    for dice in range(n_dice):
        roll_result = random.randint(1, 6)
        if roll_result >= hit_threshold:
            total_damage += damage_per_dice
        if roll_result == 6:
            total_damage += damage_per_dice # crit!
    return total_damage


def calc_damage_recieved(damage, n_armor):
    return max(damage - n_armor, 0) # no negative damage 

    
def simulate(n_simulations):
    results = np.empty((n_simulations,))
    n_dice = 6
    hit_threshold = 3
    damage_per_dice = 1
    n_armor = 2
    for i in range(n_simulations):
        damage_delt = calc_damage_dealt(
            n_dice=n_dice,
            hit_threshold=hit_threshold,
            damage_per_dice=damage_per_dice
        )
        recieved_damage = calc_damage_recieved(damage_delt, n_armor)
        results[i] = recieved_damage
    return results
    
    
results = simulate(1000)
unique, counts = np.unique(results, return_counts=True)
plt.bar(unique, counts)
plt.show()