Warhammer 40,000 example

This example applies a multiplicative handicap to the Warhammer 40,000 to-wound chart.


In [1]:
import _initpath

import numpy
import dataset.csv
import dataset.wh40k
import zerosum.balance
from pandas import DataFrame

balance_7 = zerosum.balance.MultiplicativeBalance(dataset.wh40k.wh40k_7_to_wound).optimize()
balance_8 = zerosum.balance.MultiplicativeBalance(dataset.wh40k.wh40k_8_to_wound).optimize()

labels = [str(i + 1) for i in range(10)]

dataset.csv.write_csv('out/wh40k_7_to_wound_init.csv',
                      dataset.wh40k.wh40k_7_to_wound,
                      labels)

dataset.csv.write_csv('out/wh40k_8_to_wound_init.csv',
                      dataset.wh40k.wh40k_8_to_wound,
                      labels)

dataset.csv.write_csv('out/wh40k_7_to_wound_opt.csv',
                      balance_7.F, labels,
                      row_footers = balance_7.row_handicaps / balance_7.row_handicaps[0],
                      col_footers = balance_7.col_handicaps / balance_7.col_handicaps[0],
                      numeric_format = '%0.4f')
dataset.csv.write_csv('out/wh40k_8_to_wound_opt.csv',
                      balance_8.F, labels,
                      row_footers = balance_8.row_handicaps / balance_8.row_handicaps[0],
                      col_footers = balance_8.col_handicaps / balance_8.col_handicaps[0],
                      numeric_format = '%0.4f')

7th edition to-wound chart


In [2]:
DataFrame(data = dataset.wh40k.wh40k_7_to_wound, index = labels, columns = labels)


Out[2]:
1 2 3 4 5 6 7 8 9 10
1 3.0 2.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
2 4.0 3.0 2.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0
3 5.0 4.0 3.0 2.0 1.0 1.0 0.0 0.0 0.0 0.0
4 5.0 5.0 4.0 3.0 2.0 1.0 1.0 0.0 0.0 0.0
5 5.0 5.0 5.0 4.0 3.0 2.0 1.0 1.0 0.0 0.0
6 5.0 5.0 5.0 5.0 4.0 3.0 2.0 1.0 1.0 0.0
7 5.0 5.0 5.0 5.0 5.0 4.0 3.0 2.0 1.0 1.0
8 5.0 5.0 5.0 5.0 5.0 5.0 4.0 3.0 2.0 1.0
9 5.0 5.0 5.0 5.0 5.0 5.0 5.0 4.0 3.0 2.0
10 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 4.0 3.0

7th edition resulting payoff matrix


In [3]:
DataFrame(data = balance_7.F, index = labels, columns = labels)


Out[3]:
1 2 3 4 5 6 7 8 9 10
1 3.185127 2.650938 1.827157 2.336777 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
2 2.344233 2.194957 2.017164 1.289890 2.153756 0.000000 0.000000 0.000000 0.000000 0.000000
3 1.710844 1.708695 1.766575 1.506199 1.257466 2.050221 0.000000 0.000000 0.000000 0.000000
4 1.047064 1.307185 1.441563 1.382726 1.539178 1.254768 2.027517 0.000000 0.000000 0.000000
5 0.647995 0.808976 1.115173 1.140968 1.428824 1.553074 1.254768 2.050221 0.000000 0.000000
6 0.397436 0.496171 0.683971 0.874740 1.168458 1.428824 1.539178 1.257466 2.153756 0.000000
7 0.238025 0.297158 0.409632 0.523884 0.874740 1.140968 1.382726 1.506199 1.289890 2.336777
8 0.186115 0.232352 0.320297 0.409632 0.683971 1.115173 1.441563 1.766575 2.017164 1.827157
9 0.135013 0.168554 0.232352 0.297158 0.496171 0.808976 1.307185 1.708695 2.194957 2.650938
10 0.108146 0.135013 0.186115 0.238025 0.397436 0.647995 1.047064 1.710844 2.344233 3.185127

8th edition to-wound chart


In [4]:
DataFrame(data = dataset.wh40k.wh40k_8_to_wound, index = labels, columns = labels)


Out[4]:
1 2 3 4 5 6 7 8 9 10
1 3.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
2 5.0 3.0 2.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
3 5.0 4.0 3.0 2.0 2.0 1.0 1.0 1.0 1.0 1.0
4 5.0 5.0 4.0 3.0 2.0 2.0 2.0 1.0 1.0 1.0
5 5.0 5.0 4.0 4.0 3.0 2.0 2.0 2.0 2.0 1.0
6 5.0 5.0 5.0 4.0 4.0 3.0 2.0 2.0 2.0 2.0
7 5.0 5.0 5.0 4.0 4.0 4.0 3.0 2.0 2.0 2.0
8 5.0 5.0 5.0 5.0 4.0 4.0 4.0 3.0 2.0 2.0
9 5.0 5.0 5.0 5.0 4.0 4.0 4.0 4.0 3.0 2.0
10 5.0 5.0 5.0 5.0 5.0 4.0 4.0 4.0 4.0 3.0

8th edition resulting payoff matrix


In [5]:
DataFrame(data = balance_8.F, index = labels, columns = labels)


Out[5]:
1 2 3 4 5 6 7 8 9 10
1 1.311712 0.536910 0.616361 0.738436 0.833954 0.973079 1.045450 1.191852 1.283667 1.468578
2 1.739950 1.281953 0.981103 0.587709 0.663730 0.774457 0.832056 0.948575 1.021649 1.168817
3 1.429785 1.404575 1.209317 0.965887 1.090827 0.636402 0.683733 0.779482 0.839530 0.960463
4 1.138606 1.398163 1.284049 1.153773 0.868677 1.013595 1.088979 0.620738 0.668557 0.764862
5 0.940358 1.154721 1.060477 1.270511 1.076141 0.837112 0.899371 1.025317 1.104303 0.631688
6 0.805509 0.989133 1.135504 1.088318 1.229095 1.075604 0.770400 0.878285 0.945945 1.082207
7 0.749748 0.920660 1.056898 1.012979 1.144011 1.334861 1.075604 0.817486 0.880462 1.007291
8 0.680320 0.835405 0.959027 1.148969 1.038073 1.211250 1.301335 1.112678 0.798929 0.914014
9 0.631659 0.775652 0.890432 1.066789 0.963824 1.124614 1.208256 1.377457 1.112678 0.848638
10 0.572354 0.702828 0.806831 0.966629 1.091666 1.019026 1.094815 1.248130 1.344280 1.153442

Weighting example

Optionally, instead of a uniform Nash equilibrium we can balance for a weighted Nash equilibrium.


In [6]:
strength_weights = numpy.array([0.0, 0.0, 2.0, 2.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0])
toughness_weights = strength_weights

balance_7_weighted = zerosum.balance.MultiplicativeBalance(dataset.wh40k.wh40k_7_to_wound, strength_weights, toughness_weights).optimize()

dataset.csv.write_csv('out/wh40k_7_to_wound_weighted_opt.csv',
                      balance_7_weighted.F, [str(i + 1) for i in range(10)],
                      row_footers = balance_7_weighted.row_handicaps / balance_7_weighted.row_handicaps[0],
                      col_footers = balance_7_weighted.col_handicaps / balance_7_weighted.col_handicaps[0],
                      numeric_format = '%0.4f')

DataFrame(data = balance_7_weighted.F, index = labels, columns = labels)


Out[6]:
1 2 3 4 5 6 7 8 9 10
1 3.929799 2.900320 1.745733 2.254267 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
2 2.836837 2.355388 1.890310 1.220480 1.778420 0.000000 0.000000 0.000000 0.000000 0.000000
3 1.933953 1.712785 1.546415 1.331258 0.969920 1.274734 0.000000 0.000000 0.000000 0.000000
4 1.124837 1.245249 1.199246 1.161441 1.128261 0.741418 1.408949 0.000000 0.000000 0.000000
5 0.653315 0.723252 0.870666 0.899434 0.982956 0.861245 0.818330 1.797270 0.000000 0.000000
6 0.521280 0.577083 0.694704 0.897072 1.045734 1.030780 1.305891 1.434041 2.695878 0.000000
7 0.390033 0.431786 0.519793 0.671209 0.978052 1.028337 1.465645 2.145962 2.017115 4.408250
8 0.317791 0.351810 0.423516 0.546887 0.796896 1.047334 1.592236 2.622727 3.287006 3.591750
9 0.274185 0.303536 0.365403 0.471846 0.687550 0.903624 1.717196 3.017132 4.253968 6.197814
10 0.250561 0.277383 0.333920 0.431191 0.628309 0.825766 1.569239 3.446464 5.183253 8.495700