Exemple #1
0
def iter_standard_dice():
    for die_size in [3, 4, 5, 6, 7, 8, 9, 10, 12]:
        metadata = {
            'size' : die_size,
            'threshold' : 0,
            'feature' : 'standard die',
            'faces' : [str(x) for x in range(1, die_size+1)],
            'notes' : '',
        }
        yield Die.d(die_size), metadata
Exemple #2
0
ax.set_ylabel('Chance (%) of hitting')
ax.legend(['d20', 'd20 + d6 - 3.5', 'd20 + d12 - 6.5', 'd20 + d20 - 10.5'])
plt.savefig('output/add_small_die_ccdf.png', dpi=dpi, bbox_inches="tight")

# Coin flips.

for coin_count in range(1, 11):
    fig = plt.figure(figsize=figsize)
    ax = plt.subplot(111)
    ax.grid()

    x = numpy.linspace(-3, 3, 1001)
    y = numpy.exp(-0.5 * numpy.square(x)) / numpy.sqrt(2 * numpy.pi)
    ax.plot(x, y, linestyle=':')

    coins = Die.d(coin_count, 2)
    gaussian = Die.gaussian(coins)
    ks = coins.ks_stat(gaussian) * 100.0
    print('KS %d: %0.2f%%' % (coin_count, ks))
    ax.plot((coins.outcomes() - coins.mean()) / coins.standard_deviation(),
            coins.pmf() * coins.standard_deviation(),
            marker='.')

    ax.set_xlim(-3, 3)
    ax.set_xlabel('Deviation from mean in SDs')
    ax.set_ylabel('Normalized probability')
    ax.set_ylim(0, 0.4)
    ax.set_title('%d coin(s): KS = %0.2f%%' % (coin_count, ks))

    plt.savefig('output/frames/frame_%03d.png' % (coin_count - 1),
                dpi=dpi,
Exemple #3
0
dpi = 120


def plot_extremeness(ax, die, **kwargs):
    extremeness = numpy.minimum(die.cdf(), die.ccdf())
    ax.plot(die.outcomes(), extremeness, **kwargs)


def semilogy_extremeness(ax, die, **kwargs):
    print('%0.3f | %0.3f' % (die.mean(), die.standard_deviation()))
    extremeness = numpy.minimum(die.cdf(), die.ccdf())
    extremeness[extremeness > 0.5] = 1.0
    ax.semilogy(die.outcomes(), 1.0 / extremeness, **kwargs)


die_3d6 = Die.d(3, 6)
points_3d6 = die_3d6.relabel(point_buy_to_use).repeat_and_sum(6)

die_3d6r1 = Die.d(3, 5) + 3
points_3d6r1 = die_3d6r1.relabel(point_buy_to_use).repeat_and_sum(6)

die_3d6r2 = Die.d(3, 4) + 6
points_3d6r2 = die_3d6r2.relabel(point_buy_to_use).repeat_and_sum(6)

die_4d6kh3 = Die.d(6).repeat_and_keep_and_sum(4, keep_highest=3)
points_4d6kh3 = die_4d6kh3.relabel(point_buy_to_use).repeat_and_sum(6)

die_4d6r1kh3 = Die.d(5).repeat_and_keep_and_sum(4, keep_highest=3) + 3
points_4d6r1kh3 = die_4d6r1kh3.relabel(point_buy_to_use).repeat_and_sum(6)

die_5d6kh3 = Die.d(6).repeat_and_keep_and_sum(5, keep_highest=3)
Exemple #4
0
ax = plt.subplot(111)

plot_pmf(ax,
         Die.from_faces([0] * 7 + [1] * 3).explode(100, chance=0.1),
         die_counts_simple, 'dNWoD')

ax.set_xlim(left=left, right=right)
ax.set_ylim(bottom=0)
plt.savefig('output/sum_pool_nwod.png', dpi=dpi, bbox_inches="tight")

# d6

fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)

plot_pmf(ax, Die.d(6), die_counts_standard, 'd6')

ax.set_xlim(left=left, right=right)
ax.set_ylim(bottom=0)
plt.savefig('output/sum_pool_d6.png', dpi=dpi, bbox_inches="tight")

# half-life

fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)

plot_pmf(ax, Die.d(3, 2) - 3, die_counts_standard, '(3d2-3)')

ax.set_xlim(left=left, right=right)
ax.set_ylim(bottom=0)
plt.savefig('output/sum_pool_3c.png', dpi=dpi, bbox_inches="tight")
Exemple #5
0
fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)

plot_opposed_fixed_side(ax, Die.coin(1 / 3), die_counts_simple, '(d6>=5)')

ax.set_xlim(left=left, right=right)
plt.savefig('output/add_pool_opposed_5plus.png', dpi=dpi, bbox_inches="tight")

# exalted 2e

fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)

plot_opposed_fixed_side(ax, Die.from_faces([0] * 6 + [1] * 3 + [2]),
                        die_counts_simple, 'Exalted2e')

ax.set_xlim(left=left, right=right)
plt.savefig('output/add_pool_opposed_exalted2e.png',
            dpi=dpi,
            bbox_inches="tight")

# coin

fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)

plot_opposed_fixed_side(ax, Die.d(6), die_counts_simple, '6')

ax.set_xlim(left=left, right=right)
plt.savefig('output/add_pool_opposed_d6.png', dpi=dpi, bbox_inches="tight")
Exemple #6
0
def iter_simple_dice(die_size):
    # standard die
    metadata = {
        'size' : die_size,
        'threshold' : 0,
        'feature' : 'standard die',
        'faces' : [str(x) for x in range(1, die_size+1)],
        'notes' : '',
    }
    yield Die.d(die_size), metadata
    # exploding standard die (problem: VMR too high to be useful)
    """
    metadata = {
        'size' : die_size,
        'threshold' : 0,
        'feature' : 'exploding standard die',
        'faces' : [str(x) for x in range(1, die_size+1)],
        'notes' : '',
    }
    metadata['faces'][-1] += '!'
    yield Die.d(die_size).explode(10), metadata
    """
    # odd standard dice
    if die_size % 2 == 0 and die_size >= 6 and die_size <= 10:
        metadata = {
            'size' : die_size-1,
            'threshold' : 0,
            'feature' : 'standard die',
            'faces' : [str(x) for x in range(1, die_size-1+1)],
            'notes' : '',
        }
        yield Die.d(die_size-1), metadata
    # no feature
    for i in range(1, die_size):
        faces = [0]*i + [1]*(die_size-i)
        metadata = {
            'size' : die_size,
            'threshold' : i+1,
            'feature' : 'none',
            'faces' : [str(x) for x in faces],
            'notes' : '',
            }
        if die_size == 6 and i == 3: metadata['notes'] = 'Burning Wheel'
        if die_size == 6 and i == 4: metadata['notes'] = 'Shadowrun 4e'
        yield Die.from_faces(faces), metadata
    # negative on 1
    for i in range(2, die_size):
        faces = [-1] + [0]*(i-1) + [1]*(die_size-i)
        metadata = {
            'size' : die_size,
            'threshold' : i+1,
            'feature' : '-1 success on bottom face',
            'faces' : [str(x) for x in faces],
            'notes' : '',
            }
        if die_size == 10 and i == 6: metadata['notes'] = 'Old World of Darkness'
        yield Die.from_faces(faces), metadata
    # double on max
    for i in range(1, die_size-1):
        faces = [0]*i + [1]*(die_size-i-1) + [2]
        metadata = {
            'size' : die_size,
            'threshold' : i+1,
            'feature' : '2 successes on top face',
            'faces' : [str(x) for x in faces],
            'notes' : '',
            }
        if die_size == 10 and i == 6: metadata['notes'] = 'Exalted 2e'
        yield Die.from_faces(faces), metadata
    # explode
    for i in range(1, die_size):
        faces = [0]*i + [1]*(die_size-i)
        metadata = {
            'size' : die_size,
            'threshold' : i+1,
            'feature' : 'explode on top face',
            'faces' : [str(x) for x in faces],
            'notes' : '',
            }
        metadata['faces'][-1] += '!'
        if die_size == 10 and i == 7: metadata['notes'] = 'New World of Darkness'
        yield Die.from_faces(faces).explode(100, chance=1/die_size), metadata
    """
Exemple #7
0
def test_d_multiple():
    assert Die.d(1, 2, 2).weights() == pytest.approx([2, 3, 2, 1])
Exemple #8
0
from hdroller import Die

result = ''

base_bw_dice = 24
bw_scale = 2

for pbta_bonus in [-1, 0, 1, 2, 3]:
    num_bw_dice = int(bw_scale * pbta_bonus + base_bw_dice)
    bw_die = Die.coin(0.5).repeat_and_sum(num_bw_dice)
    pbta_high_chance = Die.d(2, 6) + pbta_bonus >= 11
    pbta_mid_chance = Die.d(2, 6) + pbta_bonus >= 7

    bw_target = base_bw_dice - (base_bw_dice // 2)
    bw_high_chance = bw_die >= bw_target + int(2 * bw_scale)
    bw_mid_chance = bw_die >= bw_target

    result += '\t'.join(
        str(x) for x in [
            pbta_bonus, num_bw_dice, pbta_mid_chance, bw_mid_chance,
            pbta_high_chance, bw_high_chance
        ])
    result += '\n'

with open('output/pbta_bw.csv', mode='w') as outfile:
    outfile.write(result)
Exemple #9
0
# pf2e

fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)

ax.set_xlabel('Number needed to hit')
ax.set_ylabel('Mean damage')
ax.grid(which='both')

legend = []

x = numpy.arange(-35, 20)

semilogy_mean_damage(ax,
                     Die.d(12) + 4,
                     x=x,
                     damage=6.5,
                     linestyle='--',
                     zorder=2.1)
legend.append('d12+4, damage = 6.5')

semilogy_mean_damage_mos(ax, Die.d(24) - 1, damage_mult=1.0, x=x)
legend.append('d24-2, damage = MoS + 1')

semilogy_mean_damage_pf2e_mos(ax, Die.d(20) + 1, damage_mult=6.5, x=x)
legend.append('d20, damage = 6.5 if hit, double if MoS >= 10')

ax.set_xlim(left=-20, right=20)
ax.set_ylim(bottom=1, top=50)
ax.legend(legend, loc='upper right')
Exemple #10
0
point_buy_pathfinder = {
    3: -16,
    4: -12,
    5: -9,
    6: -6,
    7: -4,
    8: -2,
    9: -1,
    10: 0,
    11: 1,
    12: 2,
    13: 3,
    14: 5,
    15: 7,
    16: 10,
    17: 13,
    18: 17,
}

die_3d6 = Die.d(3, 6)
points_3d6 = die_3d6.relabel(point_buy_pathfinder).repeat_and_sum(6)

start_time = time.perf_counter()
repeated_result = points_3d6.keep_highest(9, 6)
end_time = time.perf_counter()

print('Repeated dice pool, 3d6x9 keep 6 highest')
print(repeated_result)
print('Computation time:', end_time - start_time)
Exemple #11
0
import matplotlib.pyplot as plt

figsize = (8, 4.5)
dpi = 120

def opposed_keep_highest(x, half_life=3):
    attack_ratio = numpy.power(0.5, x / half_life)
    ccdf = attack_ratio / (attack_ratio + 1.0)
    return Die.from_ccdf(ccdf, x[0])

left = -20
right = 20
x = numpy.arange(left * 2, right * 2+1)
okh = opposed_keep_highest(x)
laplace = Die.laplace(half_life=3)  - Die.coin(0.5)
opposed_simple = Die.d(10).explode(3) - Die.d(10).explode(3) - Die.coin(0.5)
exploding = Die.d(10).explode(3) + Die.d(1, 12)
opposed_exploding = exploding - exploding - Die.coin(0.5)

legend = [
    'Logistic, half-life = 3',
    'Opposed d10! + d12',
    'Laplace, half-life = 3',
    'Opposed d10!',
]

# ccdf

fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)
plt.savefig('output/explode_non_opposed_ideal.png', dpi = dpi, bbox_inches = "tight")

# actual

fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)

ax.set_xlabel('Target number')
ax.set_ylabel('Chance of hitting')
ax.grid(which = "both")
ax.set_title('Actual')

legend = []

for die_size in die_sizes:
    die = Die.d(die_size).explode(10)
    y = [die >= t for t in x]
    ax.semilogy(x, y)
    legend.append('d%d!' % die_size)

ax.set_xticks(xticks)
ax.set_xlim(left=0, right=20)
ax.set_ylim(top=1, bottom=1e-2)
ax.legend(legend, loc = 'lower left')
plt.savefig('output/explode_non_opposed_actual.png', dpi = dpi, bbox_inches = "tight")

# big-small

fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)
Exemple #13
0
    6: -6,
    7: -4,
    8: -2,
    9: -1,
    10: 0,
    11: 1,
    12: 2,
    13: 3,
    14: 5,
    15: 7,
    16: 10,
    17: 13,
    18: 17,
}

points_3d6 = Die.d(3, 6).relabel(point_buy_pathfinder).repeat_and_sum(6)
print(points_3d6.mean(), points_3d6.standard_deviation(),
      points_3d6.total_mass())

points_3d6_7 = Die.d(3,
                     6).relabel(point_buy_pathfinder).repeat_and_keep_and_sum2(
                         7, keep_highest=6)
print(points_3d6_7.mean(), points_3d6_7.standard_deviation(),
      points_3d6_7.total_mass())

start = time.time()
points_3d6_9 = Die.d(3,
                     6).relabel(point_buy_pathfinder).repeat_and_keep_and_sum2(
                         9, keep_highest=6)
print(points_3d6_9.mean(), points_3d6_9.standard_deviation(),
      points_3d6_9.total_mass())
Exemple #14
0
from hdroller import Die
import numpy
import matplotlib as mpl
import matplotlib.pyplot as plt

for i in range(3, 22, 2):
    median = Die.d(20).repeat_and_keep_and_sum(i, keep_middle=1)
    adv = Die.d(20).advantage(i)
    print('%dd20' % i)
    print(median.standard_deviation())
    print(adv.standard_deviation())

multi_median = Die.d(20)
for i in range(3):
    multi_median = multi_median.repeat_and_keep_and_sum(3, keep_middle=1)
    print('multimedian steps:', i+1)
    print(multi_median, multi_median.standard_deviation())

print(Die.d(20).repeat_and_keep_and_sum(3, keep_middle=1).repeat_and_keep_and_sum(7, keep_middle=1).standard_deviation())
Exemple #15
0
def test_mix_weight():
    outcomes = range(2, 13)
    mix_weights = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
    assert Die.mix(*outcomes, mix_weights=mix_weights).pmf() == pytest.approx(
        Die.d(2, 6).pmf())
Exemple #16
0
    ax.set_yticks(yticks_minor, minor=True)
    ax.set_yticklabels('%d' % t for t in yticks_major)
    ax.set_yticklabels(yticklabels_minor, minor=True)
    ax.set_ylim(bottom=0, top=top)

    ax2.set_yticks(yticks_major)
    ax2.set_yticks(yticks_minor, minor=True)
    ax2.set_yticklabels('%d' % t for t in yticks_major)
    ax2.set_yticklabels(yticklabels_minor, minor=True)
    ax2.set_ylim(bottom=0, top=top)

    plt.savefig('output/keep_highest_comparison_linear.png',
                dpi=dpi,
                bbox_inches="tight")

fig = plt.figure(figsize=figsize)
ax = plt.subplot(111)

ax.set_xlabel('1 / miss chance')
ax.set_ylabel('Number of dice / -log2(miss chance)')
ax.grid(which='major', alpha=1.0)
ax.grid(which='minor', alpha=0.25)

miss_chances = numpy.logspace(-20, 0, base=2.0)

for base_tn in range(20):
    plot_random_tn_curve(ax, Die.d6.explode(5), Die.d(2, 6), base_tn,
                         miss_chances)

plt.savefig('output/keep_highest_random_tn.png', dpi=dpi, bbox_inches="tight")