In [1]:
import _initpath
import numpy
import dataset.pokemon
import zerosum.balance
import zerosum.nash
import matplotlib
import matplotlib.pyplot as plt
type_chart = dataset.pokemon.pokemon_6
# Vector of color codes for the types.
colors = [dataset.pokemon.pokemon_type_colors[name] for name in type_chart.row_names]
After importing the dataset, we find the Nash equilibrium of the original game and the handicaps that produce a uniform Nash equilibrium.
In [2]:
row_nash, col_nash = zerosum.nash.nash(type_chart.data)
balance_result = zerosum.balance.MultiplicativeBalance(type_chart.data).optimize()
In [3]:
dpi = 240
marker_size = 64
text_size = 15
loc = matplotlib.ticker.MultipleLocator(base=0.1)
fig = plt.figure(figsize = (18, 6))
gs = matplotlib.gridspec.GridSpec(1, 2, width_ratios=[1, 1])
ax = plt.subplot(gs[0])
We draw a line indicating where a uniform Nash equilibrium would lie.
In [4]:
uniform_x = 1.0 / len(row_nash.strategy)
ax.plot([uniform_x, uniform_x], [-0.2, 0.25],
color='#bfbfbf', linestyle='-', zorder=0)
plt.text(uniform_x, -0.203, 'Uniform',
fontsize = 12,
rotation = 0,
ha = 'center', va = 'top');
Now for the scatter plot proper.
In [5]:
x = row_nash.strategy
y = numpy.log(balance_result.row_handicaps)
y -= numpy.mean(y)
ax.scatter(x, y, s = marker_size, c = colors);
We label each scatter plot point with the corresponding type name. Some manual position adjustment is involved.
In [6]:
for pointx, pointy, name, color in zip(x, y, type_chart.row_names, colors):
ha = 'left'
# manual adjustment
if name in ['Flying']:
pointy -= 0.005
if name in ['Dark']:
pointy -= 0.01
if name in ['Fairy']:
pointx -= 0.005
pointy -= 0.015
if name in ['Ground']:
ha = 'right'
name = ' ' + name + ' '
plt.text(pointx, pointy, name,
fontsize = text_size,
rotation = 0,
ha = ha, va = 'center')
ax.xaxis.set_major_locator(loc)
ax.yaxis.set_major_locator(loc)
ax.set_title('Attacker')
ax.set_xlabel('Nash probability of initial game', fontsize = text_size)
ax.set_ylabel('Log (handicap) producing uniform Nash', fontsize = text_size)
ax.set_xlim(left=0.0, right = 0.3)
ax.set_ylim(bottom=-0.2, top = 0.25);
In [7]:
ax = plt.subplot(gs[1])
uniform_x = 1.0 / len(col_nash.strategy)
ax.plot([uniform_x, uniform_x], [-0.2, 0.25],
color='#bfbfbf', linestyle='-', zorder=0)
plt.text(uniform_x, -0.203, 'Uniform',
fontsize = 12,
rotation = 0,
ha = 'center', va = 'top')
x = col_nash.strategy
y = numpy.log(balance_result.col_handicaps)
y -= numpy.mean(y)
ax.scatter(x, y, s = marker_size, c = colors)
for pointx, pointy, name, color in zip(x, y, type_chart.row_names, colors):
ha = 'left'
# manual adjustment
if name in ['Dark']:
pointx -= 0.002
pointy += 0.012
if name in ['Dragon', 'Fighting']:
pointy -= 0.01
if name in ['Normal']:
ha = 'right'
name = ' ' + name + ' '
plt.text(pointx, pointy, name,
fontsize = text_size,
rotation = 0,
ha = ha, va = 'center')
ax.xaxis.set_major_locator(loc)
ax.yaxis.set_major_locator(loc)
ax.set_title('Defender')
ax.set_xlabel('Nash probability of initial game', fontsize = text_size)
ax.yaxis.set_ticklabels([])
ax.set_xlim(left=0.0, right = 0.3)
ax.set_ylim(bottom=-0.2, top = 0.25)
plt.tight_layout();
Finally we save and display the figure.
In [8]:
plt.savefig("out/pokemon_scatter.png", dpi = dpi, bbox_inches = "tight")
plt.show()