diff --git a/pz_risk/arena.py b/pz_risk/arena.py index 412d7ce..9c5518f 100644 --- a/pz_risk/arena.py +++ b/pz_risk/arena.py @@ -1,13 +1,14 @@ from risk_env import env -from agents.greedy import GreedyAgent -from agents.random import RandomAgent +from agents import GreedyAgent, RandomAgent, ModelAgent from loguru import logger +import matplotlib.pyplot as plt e = env() e.reset() players = [GreedyAgent(i) for i in range(2)] -players += [RandomAgent(2 + i) for i in range(4)] +players += [GreedyAgent(2 + i) for i in range(2)] +players += [RandomAgent(4 + i) for i in range(2)] winner = -1 for agent in e.agent_iter(): obs, rew, done, info = e.last() diff --git a/pz_risk/demo.ipynb b/pz_risk/demo.ipynb index c965673..2f32c3a 100644 --- a/pz_risk/demo.ipynb +++ b/pz_risk/demo.ipynb @@ -1,583 +1,78 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'loss1' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_17260/627672868.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 166\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m100\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 167\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 168\u001b[0;31m \u001b[0mget_win_chance2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mj\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 169\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 170\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0md2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/tmp/ipykernel_17260/627672868.py\u001b[0m in \u001b[0;36mget_win_chance2\u001b[0;34m(attack_unit, defense_unit, left)\u001b[0m\n\u001b[1;32m 160\u001b[0m \u001b[0mwin_rate\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mget_win_chance2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mattack_unit\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdefense_unit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mloss1\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mloss2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 161\u001b[0m \u001b[0;31m# print(attack_unit, defense_unit, loss, c)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 162\u001b[0;31m \u001b[0md2\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mattack_unit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdefense_unit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mloss1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mloss2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 163\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 164\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'loss1' is not defined" - ] - } - ], - "source": [ - "import math\n", - "import numpy as np\n", - "from utils import single_roll\n", - "\n", - "\n", - "# From https://web.stanford.edu/~guertin/risk.notes.html\n", - "win_rate = np.array([\n", - " [[0.417, 0.583, 0.], # 1 vs 1\n", - " [0.255, 0.745, 0.]], # 1 vs 2\n", - " [[0.579, 0.421, 0.], # 2 vs 1\n", - " [0.228, 0.324, 0.448]], # 2 vs 2\n", - " [[0.660, 0.340, 0.], # 3 vs 1\n", - " [0.371, 0.336, 0.293]] # 3 vs 2\n", - "])\n", - "\n", - "d1 = {}\n", - "\n", - "\n", - "def get_win_chance(attack_unit, defense_unit):\n", - " global win_rate, d1\n", - "\n", - " if (attack_unit, defense_unit) in d1:\n", - " return d1[(attack_unit, defense_unit)]\n", - "\n", - " if attack_unit == 0:\n", - " c = 0.0\n", - " elif defense_unit == 0:\n", - " c = 1.0\n", - " elif attack_unit == 1:\n", - " if defense_unit == 1:\n", - " c = win_rate[0, 0, 0]\n", - " elif defense_unit == 2:\n", - " c = win_rate[0, 1, 0]\n", - " else:\n", - " c = win_rate[0, 1, 0] * get_win_chance(attack_unit, defense_unit - 1)\n", - " elif attack_unit == 2:\n", - " if defense_unit == 1:\n", - " c = win_rate[1, 0, 0] + \\\n", - " win_rate[1, 0, 1] * win_rate[0, 0, 0]\n", - " elif defense_unit == 2:\n", - " c = win_rate[1, 1, 0] + \\\n", - " win_rate[1, 1, 1] * win_rate[0, 0, 0]\n", - " else:\n", - " c = win_rate[1, 1, 0] * get_win_chance(attack_unit, defense_unit - 2) + \\\n", - " win_rate[1, 1, 1] * get_win_chance(attack_unit - 1, defense_unit - 1)\n", - " elif attack_unit == 3:\n", - " if defense_unit == 1:\n", - " c = win_rate[2, 0, 0] + \\\n", - " win_rate[2, 0, 1] * win_rate[1, 0, 0] + \\\n", - " win_rate[2, 0, 1] * win_rate[1, 0, 1] * win_rate[0, 0, 0]\n", - " else:\n", - " c = win_rate[2, 1, 0] + \\\n", - " win_rate[2, 1, 1] * win_rate[1, 0, 0] + \\\n", - " win_rate[2, 1, 1] * win_rate[1, 0, 1] * win_rate[0, 0, 0] + \\\n", - " win_rate[2, 1, 2] * win_rate[0, 1, 0]\n", - " else:\n", - " if defense_unit == 1:\n", - " c = win_rate[2, 0, 0] + \\\n", - " win_rate[2, 0, 1] * get_win_chance(attack_unit - 1, defense_unit)\n", - " else:\n", - " c = win_rate[2, 1, 0] * get_win_chance(attack_unit, defense_unit - 2) + \\\n", - " win_rate[2, 1, 1] * get_win_chance(attack_unit - 1, defense_unit - 1) + \\\n", - " win_rate[2, 1, 2] * get_win_chance(attack_unit - 2, defense_unit)\n", - " d1[(attack_unit, defense_unit)] = c\n", - " return c\n", - "\n", - "d2 = {}\n", - "def get_win_chance2(attack_unit, defense_unit, left):\n", - " global win_rate, d2\n", - "\n", - " if (attack_unit, defense_unit, left) in d2:\n", - " return d2[(attack_unit, defense_unit, left)]\n", - "\n", - " if left < -defense_unit or left > attack_unit:\n", - " c = 0.0\n", - " elif attack_unit == 0:\n", - " if left <= 0:\n", - " c = 1.0\n", - " else:\n", - " c = 0.0\n", - " elif defense_unit == 0:\n", - " if left > 0:\n", - " c = 1.0\n", - " else:\n", - " c = 0.0\n", - " elif attack_unit == 1:\n", - " if defense_unit == 1:\n", - " if left == attack_unit:\n", - " c = win_rate[0, 0, 0]\n", - " else:\n", - " c = win_rate[0, 0, 1]\n", - " elif defense_unit == 2:\n", - " if left == attack_unit:\n", - " c = win_rate[0, 1, 0] * win_rate[0, 0, 0]\n", - " elif left == 0:\n", - " c = win_rate[0, 1, 0] * win_rate[0, 0, 1]\n", - " else:\n", - " c = win_rate[0, 1, 1]\n", - " else:\n", - " if left == attack_unit:\n", - " c = win_rate[0, 1, 0] * get_win_chance2(attack_unit, defense_unit - 1, left)\n", - " elif left == -defense_unit:\n", - " c = win_rate[0, 1, 1]\n", - " else:\n", - " c = win_rate[0, 1, 0] * get_win_chance2(attack_unit, defense_unit - 1, left)\n", - " elif attack_unit == 2:\n", - " if defense_unit == 1:\n", - " if loss1 == 0:\n", - " c = win_rate[1, 0, 0]\n", - " elif loss1 == 1:\n", - " c = win_rate[1, 0, 1] * win_rate[0, 0, 0]\n", - " else:\n", - " c = win_rate[1, 0, 2]\n", - " elif defense_unit == 2:\n", - " if loss1 == 0:\n", - " c = win_rate[1, 1, 0]\n", - " elif loss1 == 1:\n", - " c = win_rate[1, 1, 1] * win_rate[0, 0, 0]\n", - " else:\n", - " c = win_rate[1, 1, 1] * win_rate[0, 1, 1]\n", - " else:\n", - " if loss1 == 0:\n", - " c = win_rate[1, 1, 0] * get_win_chance2(attack_unit, defense_unit - 2, loss1, loss2 - 2)\n", - " elif loss1 == 1:\n", - " c = win_rate[1, 1, 0] * get_win_chance2(attack_unit, defense_unit - 2, loss1, loss2 - 2) + \\\n", - " win_rate[1, 1, 1] * get_win_chance2(attack_unit - 1, defense_unit - 1, loss1 - 1, loss2 - 1)\n", - " else:\n", - " c = win_rate[1, 1, 2] + \\\n", - " win_rate[1, 1, 0] * get_win_chance2(attack_unit, defense_unit - 2, loss1, loss2 - 2) + \\\n", - " win_rate[1, 1, 1] * get_win_chance2(attack_unit - 1, defense_unit - 1, loss1 - 1, loss2 - 1)\n", - " elif attack_unit == 3:\n", - " if defense_unit == 1:\n", - " if loss1 == 0:\n", - " c = win_rate[2, 0, 0]\n", - " elif loss1 == 1:\n", - " c = win_rate[2, 0, 1] * win_rate[1, 0, 0]\n", - " elif loss1 == 2:\n", - " c = win_rate[2, 0, 1] * win_rate[1, 0, 1] * win_rate[0, 0, 0]\n", - " else:\n", - " c = win_rate[2, 0, 1] * win_rate[1, 0, 1] * win_rate[0, 0, 1]\n", - " else:\n", - " if loss1 == 0:\n", - " c = win_rate[2, 1, 0] * get_win_chance2(attack_unit, defense_unit - 2, loss1, loss2 - 2)\n", - " elif loss1 == 1:\n", - " c = win_rate[2, 1, 0] * get_win_chance2(attack_unit, defense_unit - 2, loss1, loss2 - 2) + \\\n", - " win_rate[2, 1, 1] * get_win_chance2(attack_unit - 1, defense_unit - 1, loss1 - 1, loss2 - 1)\n", - " else:\n", - " c = win_rate[2, 1, 2] * get_win_chance2(attack_unit - 2, defense_unit, loss1 - 2, loss2) + \\\n", - " win_rate[2, 1, 1] * get_win_chance2(attack_unit - 1, defense_unit - 1, loss1 - 1, loss2 - 1) + \\\n", - " win_rate[2, 1, 0] * get_win_chance2(attack_unit, defense_unit - 2, loss1, loss2 - 2)\n", - " else:\n", - " if defense_unit == 1:\n", - " if loss1 == 0:\n", - " c = win_rate[2, 0, 0]\n", - " else:\n", - " c = win_rate[2, 0, 1] * get_win_chance2(attack_unit - 1, defense_unit, loss1 - 1, loss2 - 1)\n", - " else:\n", - " c = win_rate[2, 1, 0] * get_win_chance2(attack_unit, defense_unit - 2, loss1, loss2 - 2) + \\\n", - " win_rate[2, 1, 1] * get_win_chance2(attack_unit - 1, defense_unit - 1, loss1 - 1, loss2 - 1) + \\\n", - " win_rate[2, 1, 2] * get_win_chance2(attack_unit - 2, defense_unit, loss1 - 2, loss2)\n", - "# print(attack_unit, defense_unit, loss, c)\n", - " d2[(attack_unit, defense_unit, loss1, loss2)] = c\n", - " return c\n", - "\n", - "for i in range(1, 100):\n", - " for j in range(1, 100):\n", - " for r in range(0, i):\n", - " get_win_chance2(i, j, r)\n", - "\n", - "print(len(d2))\n", - "\n", - "\n", - "# from mpl_toolkits import mplot3d\n", - "\n", - "#\n", - "# fig = plt.figure()\n", - "# ax = plt.axes(projection='3d')\n", - "# X, Y, Z, C = [k[0] for k in d.keys()], [k[1] for k in d.keys()], [v for v in d.values()], [k[2] for k in d.keys()]\n", - "# img = ax.scatter(X, Y, Z, c=C, cmap=plt.hot()) # rstride=1, cstride=1, cmap='viridis', edgecolor='none')\n", - "# fig.colorbar(img)\n", - "# ax.set_xlabel('Attack')\n", - "# ax.set_ylabel('Defense')\n", - "# # ax.set_zlabel('Loss')\n", - "# ax.view_init(20, 70)\n", - "#\n", - "#\n", - "# plt.show()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "def plot_me(x, y, data):\n", - " X = [k[2] for k, v in data.items() if k[0] == x and k[1] == y and 0 <= k[2] <= x]\n", - " Y = [v for k, v in data.items() if k[0] == x and k[1] == y and 0 <= k[2] <= x]\n", - " W = [k[3] for k, v in data.items() if k[0] == x and k[1] == y and 0 <= k[3] <= y]\n", - " Z = [v for k, v in data.items() if k[0] == x and k[1] == y and 0 <= k[3] <= y]\n", - " print(X)\n", - " print(Y)\n", - " print(W)\n", - " print(Z)\n", - " print(X[np.argmax(Y)], np.mean(Y), np.std(Y), sum(Y))\n", - " print(W[np.argmax(Z)], np.mean(Z), np.std(Z), sum(Z))\n", - " fig, ax = plt.subplots()\n", - " ax.plot(X, Y)\n", - " ax.plot(W, Z)\n", - " ax.grid()\n", - " plt.show() \n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'plot_me' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_17260/981600773.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m40\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m10\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mplot_me\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0md2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mget_win_chance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;31m# x_axis = np.arange(0, a, 0.1)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'plot_me' is not defined" - ] - } - ], - "source": [ - "from scipy.stats import norm\n", - "\n", - "a, b = 40, 10\n", - "plot_me(a, b, d2)\n", - "print(get_win_chance(a, b))\n", - "# x_axis = np.arange(0, a, 0.1)\n", - "\n", - "# plt.plot(x_axis, norm.pdf(x_axis,16,6))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "dd = {}\n", - "n = 1000\n", - "a, b = 15, 20\n", - "for i in range(n):\n", - " ta = int(a)\n", - " td = int(b)\n", - " while ta > 0 and td > 0:\n", - " la, ld = single_roll(ta, td)\n", - " ta -= la\n", - " td -= ld\n", - " \n", - " left = ta if ta > td else -td\n", - " if (a, b, left) not in dd:\n", - " dd[(a, b, left)] = 0.0\n", - " dd[(a, b, left)] += 1.0/n" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "ename": "IndexError", - "evalue": "tuple index out of range", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_17260/177707147.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0md4\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mdd\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdd\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdd\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mplot_me\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0md4\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0md4\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/tmp/ipykernel_17260/2118388527.py\u001b[0m in \u001b[0;36mplot_me\u001b[0;34m(x, y, data)\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mX\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0my\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mY\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mv\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0my\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0mW\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0my\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0mZ\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mv\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0my\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mX\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/tmp/ipykernel_17260/2118388527.py\u001b[0m in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mX\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0my\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mY\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mv\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0my\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0mW\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0my\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0mZ\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mv\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0my\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mX\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mIndexError\u001b[0m: tuple index out of range" - ] - } - ], - "source": [ - "d4 = {(a, b, i-b): dd[(a,b,i-b)] for i in range(len(dd)+1) if (a,b,i-b) in dd}\n", - "plot_me(a, b, d4)\n", - "d4" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "d3 = {}\n", - "def get_chance(attack_unit, defense_unit, left):\n", - " global win_rate, d3\n", - " i_a = min(attack_unit - 1, 2)\n", - " i_d = min(defense_unit - 1, 1)\n", - " #print(attack_unit, defense_unit, left)\n", - " if (attack_unit, defense_unit, left) in d3:\n", - " c = d3[(attack_unit, defense_unit, left)]\n", - " #print(attack_unit, defense_unit, left, c)\n", - " return c\n", - "\n", - " c = 0.0\n", - " if left < -defense_unit or left > attack_unit:\n", - " c = 0.0\n", - " elif defense_unit < 0 or attack_unit < 0:\n", - " c = 0.0\n", - " elif attack_unit == 0:\n", - " if left == -defense_unit:\n", - " c = 1.0\n", - " else:\n", - " c = 0.0\n", - " elif defense_unit == 0:\n", - " if left == attack_unit:\n", - " c = 1.0\n", - " else:\n", - " c = 0.0\n", - " else: \n", - " c = win_rate[i_a, i_d, 0] * get_chance(attack_unit, defense_unit - min(min(i_a, i_d) + 1, 2), left) + \\\n", - " win_rate[i_a, i_d, 1] * get_chance(attack_unit - 1, defense_unit - min(i_a, 1), left) + \\\n", - " win_rate[i_a, i_d, 2] * get_chance(attack_unit - 2, defense_unit, left)\n", - " #print(attack_unit, defense_unit, left, c)\n", - " d3[(attack_unit, defense_unit, left)] = c\n", - " return c" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.040446578336175" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "get_chance(5, 3, -1)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1043851\n" - ] - } - ], - "source": [ - "for i in range(1, 100):\n", - " for j in range(1, 100):\n", - " for r in range(-j, i):\n", - " get_chance(i, j, r)\n", - "\n", - "print(len(d3))" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "def plot_me(x, y, data):\n", - " X = [k[2] for k, v in data.items() if k[0] == x and k[1] == y and -y <= k[2] <= x]\n", - " Y = [v for k, v in data.items() if k[0] == x and k[1] == y and -y <= k[2] <= x]\n", - " win = sum([v for k, v in data.items() if k[0] == x and k[1] == y and 0 <= k[2] <= x])\n", - " print(X[np.argmax(Y)], np.max(Y), sum(Y), win)\n", - " fig, ax = plt.subplots()\n", - " ax.plot(X, Y)\n", - " ax.grid()\n", - " plt.show()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-4 0.448 1.0 0.09157402170000001\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plot_me(2, 4, d3)" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-6 0.1659419095 1.0 0.12873976072661206\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAD4CAYAAADlwTGnAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAvPUlEQVR4nO3dd3hUZfbA8e9JTyAQIBAg9E4oAqEKsqC7FAtYcAUbuigWcHX154q6orJ23WUtsIqIiA1ZUEQEsRFEECT0DiG0ANJbgCQkOb8/MuzGGMikTO6U83meeXLLe985x5F75r5zi6gqxhhjAk+Q0wEYY4xxhhUAY4wJUFYAjDEmQFkBMMaYAGUFwBhjAlSI0wEUR2xsrDZo0KBE2546dYoKFSqUbUAO8Zdc/CUPsFy8lb/kUto8li9ffkhVqxdc7lMFoEGDBiQnJ5do26SkJHr16lW2ATnEX3LxlzzAcvFW/pJLafMQkZ2FLbchIGOMCVBWAIwxJkBZATDGmABlBcAYYwKUFQBjjAlQVgCMMSZAWQEwxpgA5VPXAQQ6VWXW6r1knc51OhRjjB+wAuAjVJUXv9rMmwu2UTc6iIF9cgkLsQM4Y0zJ2R7ER4z9ditvLthGt0bV2H0ylzcXbHM6JGOMj7MC4APGzU/hte+28seOdfjwji50qRnM699vZfMvJ50OzRjjw6wAeLm3f0jl5XmbuaZ9PM9f25agIOGmhHCiI0L56/TVZOfY7wHGmJKxAuDFJi/azrNzNnJFm1q8PKgtwUECQKUw4akBrViddpxJi7Y7HKUxxldZAfBSHy7dyVNfbKBPQhz/GtyOkOBff1RXta3FHxLi+MfXW9h+6JRDURpjfJkVAC80LXk3j3+2jktb1OD1G9sTGvzbj0lEeObq1oSFBPHI9DXk5qoDkRpjfJkVAC8zc+UeHpmxhkuaxjL+pg6EhwSft21cpQieuDKBn3cc4cOlhd7u2xhjzssKgBf5cs0+Hpy2iq4NqzHhlo5EhJ5/53/O9Yl1uKRpLC/M3UTa0dPlEKUxxl9YAfASX6//hfunrqRDvSpMHNqRyLCid/6QNxT0/LVtAHj007Wo2lCQMcY9VgC8wPxNBxjx0Qpax1fm3ds7USG8eBdo16kSxSP9W7Bw6yH+szzNQ1EaY/yNFQCH/bDlIHd9sJzmNaN570+diY4ILVE/N3epT+cGVXlm9gb2n8go4yiNMf7ICoCDftp2mDunJNMotgIfDOtC5ciS7fwBgoKEFwe1JTM7l7/NXGdDQcaYIlkBcEjyjiMMe28Z9apG8eEdXYiJCit1nw1jK/BQn2Z8s2E/s9fsK4MojTH+zAqAA1buOspt7y6jZqUIPryzC9UqhpdZ38N6NOKiujE8OWs9h9Mzy6xfY4z/sQJQztbtOc6tk36maoUwPrqzKzWiI8q0/+Ag4eVBbTmZcZanvthQpn0bY/yLWwVARPqJyGYRSRGRUYWs7ykiK0QkW0QGFViXIyKrXK9Z+ZY3FJGlrj4/EZHSj4F4uQ17T3DzO0upFBHKR3d2oWblst35n9MsLpr7Lm3KF6v38vX6XzzyHsYY31dkARCRYGAc0B9IAIaISEKBZruA24CPCunijKq2c70G5Fv+IjBWVZsAR4FhJYjfZ2zdf5Kb31lKREgwH9/ZlTpVojz6fvf0akyLmtH8beY6jp8569H3Msb4JneOADoDKaqaqqpZwFRgYP4GqrpDVdcAbt2bWEQEuBSY7lr0HnC1u0H7mtSD6dw4cSnBQcLHw7tSr5pnd/4AocFBvDzoIg6fyuLZL20oyBjzW+5ccRQP7M43nwZ0KcZ7RIhIMpANvKCqM4FqwDFVzc7XZ3xhG4vIcGA4QFxcHElJScV46/9JT08v8balceB0Ls8vzSBblVGdI9m5bhmlvWtPcXLpVz+Eaclp1OMgrWO96wmgTn0mnmC5eCd/ycVTeZTHHqG+qu4RkUbA9yKyFjju7saqOgGYANCxY0ft1atXiYJISkqipNuWVNrR0zz+1hI0OIRpd3alZa1KZdJvcXLp2j2Hja8t5OOUXOZd1YOKxbzK2JOc+Ew8xXLxTv6Si6fycGcIaA9QN998Hdcyt6jqHtffVCAJaA8cBmJE5NzeqFh9+oJ9x88w5O0lnMw4ywfDupTZzr+4IkKDeXlQW/YeP8NLX21yJAZjjHdypwAsA5q6ztoJAwYDs4rYBgARqSIi4a7pWKA7sEHzLlOdD5w7Y2go8Hlxg/dWB05kcOPbSzl66ixThnWhdXxlR+NJrF+V2y5uwJSfdvLz9iOOxmKM8R5FFgDXOP1IYB6wEZimqutFZIyIDAAQkU4ikgZcD7wlIutdm7cEkkVkNXk7/BdU9dwvko8AD4pICnm/CbxTlok55VB6JjdOXMr+Exm896dOtKsb43RIADzctzl1q0byyIw1ZJzNcTocY4wXcGtAWFXnAHMKLBudb3oZecM4BbdbDLQ5T5+p5J1h5DeOnsri5olLSTt6msm3dyaxflWnQ/qvqLAQXri2LTdNXMrYb7bw6OUtnQ7JGOMwuxK4jBw4mcEtk5aSeugUE2/tRNdG1ZwO6Te6N4llSOe6vL0wldW7jzkdjjHGYVYASik7J5dJP27nslcWsGV/Om/dnEiPprFOh3Vej17ekhrRETw8fTWZ2TYUZEwgswJQCst2HOHK139kzOwNtK9fhXkP9KR3ixpOh3VBlSJCee7a1mzZn864+ducDscY4yDvOSnchxw8mcnzczfy6Yo9xMdE8ubNifRtFUfeBc7e79IWcVzTPp7x81Po37qmY6eoGmOcZUcAxZCdk8vkRdu59B9JfLF6LyN6N+abB3vSr3VNn9n5nzP6ygRiokL56/Q1ZOe4dQcPY4yfsQLgpuQdR7jqjUU89cUG2tWNYd4DPXm4bwuiwnzzIKpKhTDGDGzN2j3HeXvhdqfDMcY4wDf3XuXoUHomL8zdxPTladSqHMG/b+rgk9/4C3N5m1r0a1WTsd9uoU+rOBpXr+h0SMaYcmRHAOeRk6tM+WkHl76SxOer9nBPr8Z899Dv6N+mll/s/M8Zc3UrIkOD+ev0NeTk2nOEjQkkVgAKsXznUQa88SOjP19P2zoxzL2/J4/0893hngupER3Bk1clsHznUab8tMPpcIwx5cj/9milcDg9kxe/2sS05DRqVopg3I0duLyNfwz3XMg17eOZtXovL321mctaxJXL8wqMMc6zIwDyhnveX7KT3q8k8emKPdz1u0Z899DvuKKtfw33nI+I8Nw1bQgOEkZ9uoa8e/UZY/xdwB8BrNx1lCc+X8e6PSe4uHE1xgxsRZMa0U6HVe5qx0Ty6OUtePyzdUxdtpshnes5HZIxxsMCtgAcOZXFS19tYuqy3cRVCuf1Ie25MkC+8Z/PkE71mL16H899uZFezatTq3Kk0yEZYzwo4IaAcnKVD5fmDfdMX57GXT0b8d1DvbjqotoBvfMHCAoSXriuDWdzc/nLJ6s4cirL6ZCMMR4UUAVg9e5jXDN+EY9/to6WtaKZe/8lPHp5S696TKLT6lerwDNXt2H5zqP0GbuAeet/cTokY4yHBMSe7+ipLCavy2TBvEVUrxjOq4PbMcC+8Z/XoMQ6tKpdiYemreau95dzTft4nrwqgZioMKdDM8aUoYAoAHdOSWbFnmzu6NGQP1/WlOiIUKdD8nota1Vi5ojujJufwrj5KSxKOcQL17Xh0hZxTodmjCkjATEE9PgVLRlzcSSPX5FgO/9iCAsJ4i9/aMbMEd2pEhXGnyYn8/B/VnMi46zToRljykBAFID29apQJzogUvWI1vGVmXVfd0b0bsyMFWn0HfsDC7YcdDosY0wp2V7RuCU8JJiH+7bg03u7UyE8hKGTfubRT9eQnpntdGjGmBKyAmCKpV3dGGbf14O7ejZi6rLd9B37A4tTDjkdljGmBNwqACLST0Q2i0iKiIwqZH1PEVkhItkiMijf8nYi8pOIrBeRNSJyQ751k0Vku4iscr3alUlGxuMiQoN59PKWTL+7G2EhQdw4cSmjP1/HKTsaMManFFkARCQYGAf0BxKAISKSUKDZLuA24KMCy08Dt6pqK6Af8C8Ricm3/mFVbed6rSpRBsYxifWrMufPl/Cn7g15f8lO+r+6kKWph50OyxjjJneOADoDKaqaqqpZwFRgYP4GqrpDVdcAuQWWb1HVra7pvcABoHqZRG68QmRYMKOvSmDqnV0BGPz2Ep7+Yj1nsnIcjswYUxQp6s6PriGdfqp6h2v+FqCLqo4spO1kYLaqTi9kXWfgPaCVqua62nYDMoHvgFGqmlnIdsOB4QBxcXGJU6dOLVaC56Snp1Oxon888cpbc8nMVqZtyeK7XdnERQl3tAmnaZXg87b31jxKwnLxTv6SS2nz6N2793JV7fibFap6wRcwCJiYb/4W4I3ztJ0MDCpkeS1gM9C1wDIBwskrDKOLiiUxMVFLav78+SXe1tt4ey6Lth7Ui5//ThuMmq3PfrlBz2RlF9rO2/MoDsvFO/lLLqXNA0jWQvap7gwB7QHq5puv41rmFhGpBHwJPK6qS/IVnn2u2DKBd8kbajJ+4OImsXz1wCUM7lSPCT+kcsVrC1m1+5jTYRljCnCnACwDmopIQxEJAwYDs9zp3NX+M2CKFhgWEpFarr8CXA2sK0bcxstFR4Ty/LVtmPKnzpzOyuHa8Yt46atNZGbbbwPGeIsiC4CqZgMjgXnARmCaqq4XkTEiMgBARDqJSBpwPfCWiKx3bf5HoCdwWyGne34oImuBtUAs8ExZJma8Q89m1fnqgZ5c16EO45O2MeD1Razbc9zpsIwxuHkzOFWdA8wpsGx0vull5A0NFdzuA+CD8/R5abEiNT6rcmQoL19/Ef1a1+TRT9cycNwiRvRuQttge/SkMU6yK4FNubmsZRxf/6UnAy6qzWvfbWXMTxkcSv/NiV/GmHJiBcCUq5ioMMbe0I63bklkb3ouf5+9wemQjAlYVgCMI/q2qskVjUL5fNVeFm61O4sa4wQrAMYxVzQKpWFsBZ6YuY6Ms3Z2kDHlzQqAcUxYsPD3ga3Zcfg04+enOB2OMQHHCoBxVI+msVzdrjb/XrCNlAPpTodjTECxAmAc9/gVCUSGBvP4Z2vP3SbEGFMOrAAYx1WPDmdU/5Ys3X6EGSvcvsuIMaaUrAAYrzC4U1061IvhuTkbOXoqy+lwjAkIVgCMVwgKEp69pg3Hz5zl+bkbnQ7HmIBgBcB4jZa1KnFHj4ZMS07j5+1HnA7HGL9nBcB4lft/35T4mEge+2wtWdm5RW9gjCkxKwDGq0SFhTBmYCtSDqTz9sJUp8Mxxq9ZATBe57KWcfRrVZPXvtvKzsOnnA7HGL9lBcB4pScHJBASJDzx+Xq7NsAYD7ECYLxSrcqRPNSnOT9sOcjsNfucDscYv2QFwHitoRc3oHV8JcbM3sDxM2edDscYv2MFwHit4CDhuWvacDg9k1fmbXY6HGP8jhUA49Xa1onh1m4N+GDpTlbtPuZ0OMb4FSsAxus91KcZNaLDeezTtWTn2LUBxpQVKwDG60VHhPLkVa3YsO8EkxfvcDocY/yGWwVARPqJyGYRSRGRUYWs7ykiK0QkW0QGFVg3VES2ul5D8y1PFJG1rj5fExEpfTrGX/VvXZPezavzz2+2sOfYGafDMcYvFFkARCQYGAf0BxKAISKSUKDZLuA24KMC21YFngS6AJ2BJ0Wkimv1v4E7gaauV78SZ2H8nogwZmBrclV5atZ6p8Mxxi+4cwTQGUhR1VRVzQKmAgPzN1DVHaq6Big4QNsX+EZVj6jqUeAboJ+I1AIqqeoSzbvKZwpwdSlzMX6ubtUo7r+sGd9s2M/X639xOhxjfF6IG23igd355tPI+0bvjsK2jXe90gpZ/hsiMhwYDhAXF0dSUpKbb/1r6enpJd7W2/hLLiXJo2muUqeiMOo/K8jdF0lEiHeMHPrLZwKWizfyVB7uFABHqeoEYAJAx44dtVevXiXqJykpiZJu6238JZeS5lGl8RGu+/dPJGfE8bcrC45GOsNfPhOwXLyRp/JwZwhoD1A333wd1zJ3nG/bPa7pkvRpAlxi/aoM6VyXdxfvYP3e406HY4zPcqcALAOaikhDEQkDBgOz3Ox/HtBHRKq4fvztA8xT1X3ACRHp6jr751bg8xLEbwLUI/1aEBMZymOfrSMn124WZ0xJFFkAVDUbGEneznwjME1V14vIGBEZACAinUQkDbgeeEtE1ru2PQL8nbwisgwY41oGcC8wEUgBtgFzyzQz49diosL425UtWb37GB8t3el0OMb4JLd+A1DVOcCcAstG55texq+HdPK3mwRMKmR5MtC6OMEak9/V7eKZvjyNl77aTN9WNalRKcLpkIzxKXYlsPFZIsLfB7YmMzuXMbM3OB2OMT7HCoDxaY2qV+Te3o2ZvWYfC7YcdDocY3yKFQDj8+7p1ZhGsRV4YuY6Ms7mOB2OMT7DCoDxeeEhwTxzTWt2HTnN699vdTocY3yGFQDjFy5uHMu17eOZ8EMqW/efdDocY3yCFQDjNx67oiVRYSE8/tk6cu3aAGOKZAXA+I3YiuE82r8FP+84wvTlaUVvYEyAswJg/MofO9alY/0qPDd3I4fTM50OxxivZgXA+JWgIOG5a9uQnpHNc3M2OR2OMV7NCoDxO83iormzZyNmrEjjp22HnQ7HGK9lBcD4pT9f2pS6VSN5fOZaMrPt2gBjCmMFwPilyLBgxgxsTerBUzw1awNncwo+rM4YYwXA+K3ezWtw5yUN+fjnXQyZsIRfjmc4HZIxXsUKgPFrj1+RwKuD27Fh3wkuf20hC7fa/YKMOccKgPF7A9vFM2tkd2IrhnHrpJ8Z+80We4iMMVgBMAGiSY1oZo7ozjXt43n1u60MnfQzh+w6ARPgrACYgBEVFsI/rr+IF69rw7IdR7j81YX8vP1I0Rsa46esAJiAIiLc0Kken93bnaiwYIa8vYQ3F2yzeweZgGQFwASkhNqVmHVfD/okxPHC3E0Mfz+ZY6eznA7LmHJlBcAErEoRoYy/qQNPXpXAgi0HueK1H1m9+5jTYRlTbtwqACLST0Q2i0iKiIwqZH24iHziWr9URBq4lt8kIqvyvXJFpJ1rXZKrz3PrapRlYsa4Q0S4vXtDpt3VDYBBby7mvcU7ULUhIeP/iiwAIhIMjAP6AwnAEBFJKNBsGHBUVZsAY4EXAVT1Q1Vtp6rtgFuA7aq6Kt92N51br6oHSp2NMSXUvl4VZt/Xgx5NYnly1nru+3gl6ZnZTodljEe5cwTQGUhR1VRVzQKmAgMLtBkIvOeang5cJiJSoM0Q17bGeKUqFcJ4Z2gnHu7bnDlr9zHg9R/ZuO+E02EZ4zHuFIB4YHe++TTXskLbqGo2cByoVqDNDcDHBZa96xr+eaKQgmFMuQsKEkb0bsJHd3blZGY2V49bxLTk3UVvaIwPkqLGOkVkENBPVe9wzd8CdFHVkfnarHO1SXPNb3O1OeSa7wJMVNU2+baJV9U9IhINzAA+UNUphbz/cGA4QFxcXOLUqSU7iEhPT6dixYol2tbb+Esu3p7H8UzlzdUZbDySS4/4EG5JCCM8uPDvKd6eS3FYLt6ntHn07t17uap2/M0KVb3gC+gGzMs3/yjwaIE284BurukQ4BCu4uJaNhZ47ALvcRvwRlGxJCYmaknNnz+/xNt6G3/JxRfyyM7J1VfmbdL6j8zWvmMXaMqBk4W284Vc3GW5eJ/S5gEkayH7VHeGgJYBTUWkoYiEAYOBWQXazAKGuqYHAd+73hQRCQL+SL7xfxEJEZFY13QocCWwzo1YjClXwUHCQ32aM/n2Tuw/kcGA13/ki9V7nQ7LmDJRZAHQvDH9keR9y98ITFPV9SIyRkQGuJq9A1QTkRTgQSD/qaI9gd2qmppvWTgwT0TWAKuAPcDbpU3GGE/p1bwGX/75EprXjOa+j1cy+vN19qAZ4/NC3GmkqnOAOQWWjc43nQFcf55tk4CuBZadAhKLGasxjqodE8knd3XjxbmbmPjjdlbvPsYbN3agbtUop0MzpkTsSmBjiiE0OIi/XZnAmzcnknrwFFe8tpBvN+x3OixjSsQKgDEl0K91TWb/uQd1q0Zxx5RkZmy1+wgZ32MFwJgSql+tAjPuuZhr28fzxbazrEk75nRIxhSLFQBjSiEiNJinB7YiMgTGzU9xOhxjisUKgDGlFB0Ryu/rhzJv/X627j/pdDjGuM0KgDFloE/9UCJDgxmftM3pUIxxmxUAY8pAdJhwU5d6zFq9l12HTzsdjjFusQJgTBm5s2cjgkV48wc7CjC+wQqAMWUkrlIEgzrWYXpyGr8cz3A6HGOKZAXAmDJ0d8/G5KgycWFq0Y2NcZgVAGPKUL1qUQy4qDYfLt3FkVN2cZjxblYAjClj9/RqzJmzOUxetN3pUIy5ICsAxpSxZnHR9G0Vx+TFOziZcdbpcIw5LysAxnjAiN5NOJGRzQdLdjkdijHnZQXAGA9oWyeGS5rG8s6PqWSctecGGO9kBcAYDxnZuwmH0rP4ZJk9VN54JysAxnhI54ZV6Vi/Cm8t2EZWdq7T4RjzG1YAjPEQEWHEpU3YezyDmSv3OB2OMb9hBcAYD+rVrDqtalfi3wu2kZOrTodjzK9YATDGg0SEEb2bsP3QKeas3ed0OMb8ihUAYzysX6uaNK5egXHzU1C1owDjPdwqACLST0Q2i0iKiIwqZH24iHziWr9URBq4ljcQkTMissr1ejPfNokista1zWsiImWWlTFeJChIuKdXEzb9cpLvNx1wOhxj/qvIAiAiwcA4oD+QAAwRkYQCzYYBR1W1CTAWeDHfum2q2s71ujvf8n8DdwJNXa9+JU/DGO82sF1t4mMiecOOAowXcecIoDOQoqqpqpoFTAUGFmgzEHjPNT0duOxC3+hFpBZQSVWXaN6/hinA1cUN3hhfERocxN2/a8TKXcf4KfWw0+EYA0CIG23igfxXsqQBXc7XRlWzReQ4UM21rqGIrAROAH9T1YWu9mkF+owv7M1FZDgwHCAuLo6kpCQ3Qv6t9PT0Em/rbfwlF3/JA9zLJS5HqRQmPPvpMh7uFFk+gZVAoH0uvsBTebhTAEpjH1BPVQ+LSCIwU0RaFacDVZ0ATADo2LGj9urVq0SBJCUlUdJtvY2/5OIveYD7uYwI2cbzczcR07gd7erGeDyukgjEz8XbeSoPd4aA9gB1883XcS0rtI2IhACVgcOqmqmqhwFUdTmwDWjmal+niD6N8Ts3da1P5chQxs1PcToUv3cmK4fMbPu95ULcOQJYBjQVkYbk7aQHAzcWaDMLGAr8BAwCvldVFZHqwBFVzRGRRuT92JuqqkdE5ISIdAWWArcCr5dNSsZ4r4rhIdzevQH/+nYrm345QYualZwOyS9t3HeCP775Eyczs4n64SuqR4cTWzGc6hXDiY0Oy5s+tyzatbxiOJFhwU6HXq6KLACuMf2RwDwgGJikqutFZAyQrKqzgHeA90UkBThCXpEA6AmMEZGzQC5wt6oeca27F5gMRAJzXS9j/N5tFzfg7R9SGT9/G68Nae90OH4n42wOD0xdRXhoMH3rC5Wq1+FQeiYHT2ay7WA6S7Zncux04c9pqBgeQmzFsF8Vh9iK+af/ty4i1PeLhVu/AajqHGBOgWWj801nANcXst0MYMZ5+kwGWhcnWGP8QUxUGDd3rc/bC1N58A/NaBBbwemQ/MoLczexef9JJt/eCfZtoFevgmetQ1Z2LkdOZXHwZOZ/i8PB9P9NH0rPZOuBdBZvO8zxM4UXi+jwEKpHh9OnVU0e6dccX7yUydM/AhtjCjGsR0PeXbyDNxds44Xr2jodjt+Yv/kAkxfv4LaLG9CreQ2S9m0otF1YSBA1K0dQs3JEkX1mZudwOD2LQ78qEFn/PaJ4c8E2YiuGcccljco6HY+zAmCMA2pUiuCGjnWZumwX9/++KbUqe+9pob7iUHomD/9nDc3iKjKqf4sy6zc8JJjaMZHUjvntZ6Sq3PvhCp6bs5EWNSvRo2lsmb1vebB7ARnjkOE9G5GrMOGHVKdD8XmqyqgZazhx5iyvDm5fbuPzIsIr119E0xrRjPx4BbsOny6X9y0rVgCMcUjdqlFc3S6ej3/exeH0TKfD8WkfLt3FtxsP8Ej/FrSsVb5nVlUID2HCrYmowp1TkjmVmV2u718aVgCMcdA9vRqTmZ3LpEXbnQ7FZ6UcSOeZLzdwSdNYbr+4gSMx1K9WgXE3dmDrgZP8339W+8z9nqwAGOOgJjUq0r91TaYs3smJjMLPNjHnl5Wdy/1TVxIZGsw/rr+IoCDnzsTp0TSWxy5vydx1v/DG975xoZ8VAGMcdm+vJpzMzOb9n3Y6HYrP+cc3m1m/9wQvXNeWGpWKPqPH04b1aMg17eP557db+HbDfqfDKZIVAGMc1jq+Mr2aV+edH7dzJivH6XB8xuKUQ0z4IZUhnevRt1VNp8MB8n4Ufv7aNrSuXZkHPllFyoF0p0O6ICsAxniBkb2bcORUFh//vMvpUHzCsdNZPDhtNQ2rVeCJK1s6Hc6vRIQG89YtiUSEBjF8SvJ5LyTzBlYAjPECHRtUpUvDqkz4IZXMbDsKuBBV5bHP1nIoPZNXB7cnKsz7LmeqHRPJ+JsS2XXkNA9MXUlOrnf+KGwFwBgvMaJ3E345kcFnK+zGuBcyfXkac9b+woN9mtGmTmWnwzmvzg2r8tSAVszffJB/fL3Z6XAKZQXAGC9xSdNY2tapzL8XbCM7J9fpcLzSjkOneGrWero0rMpdPRs7HU6Rbu5anyGd6zE+aRuz1+x1OpzfsAJgjJcQEe7t1YSdh0/z5dp9Tofjdc7m5PLAJ6sIDhLG3tCOYAdP+SyOpwe0omP9Kjz8nzVs2HvC6XB+xQqAMV6kT0IcTWtUZPz8beR66bixU17/PoVVu4/x3LVtCr0vj7cKCwli/M0dqBwZyvD3kzlyKsvpkP7LCoAxXiQoSLi3d2M27z/Jd5sOOB2O10jecYQ3vt/KtR3iubJtbafDKbYa0RG8dUsiB05mMvKjFV4zxGcFwBgvc1Xb2tSrGsUb81N85pYCnnQi4ywPfLKK+CqRPD2gWI8U9yoX1Y3h+WvasHjbYZ6ds9HpcAArAMZ4nZDgIO7+XWNW7z7G4m2HnQ7HcU99vp59xzP41w3tiY4IdTqcUrkusQ5/6t6QdxftYPryNKfDsQJgjDe6LjGeuErhPnNPGU/5fNUePl25h/subUJi/SpOh1MmHru8Bd2bVOOxz9ayavcxR2OxAmCMFwoPCebOSxrxU+phlu886nQ4jkg7epq/zVxHh3oxjOzdxOlwykxIcBBvDOlAjehw7no/mQMnMhyLxQqAMV7qxi71qBIVyvj5gXcUkJOrPPjJalThXze0JyTYv3ZVVSqE8fatHTlxJpu7P1ju2NXf/vVf1Rg/EhUWwp+6N+S7TQe87vxxT3tzwTZ+3nGEpwe0ol61KKfD8YiWtSrxyvUXsWLXMZ78fL0jP/i7VQBEpJ+IbBaRFBEZVcj6cBH5xLV+qYg0cC3/g4gsF5G1rr+X5tsmydXnKterRpllZYyfuLVbAyqGhzA+KXCOAlbvPsbYb7ZwZdtaXNsh3ulwPOqKtrUY0bsxU5ft5oOl5X8jwCILgIgEA+OA/kACMEREEgo0GwYcVdUmwFjgRdfyQ8BVqtoGGAq8X2C7m1S1netlJz0bU0DlqFBu6VafL9fuI/Wgd99auCycyszmgU9WUSM6nGevboOIb1ztWxoP/aE5l7aowdOz1rM0tXzP+nLnCKAzkKKqqaqaBUwFBhZoMxB4zzU9HbhMRERVV6rquRtgrAciRSS8LAI3JlAM69GQsOAg3lywzelQPO7vszew4/Ap/nlDOypH+fYpn+4KChL+Nbgd9apFce+HK9hz7Ey5vbcUNe4kIoOAfqp6h2v+FqCLqo7M12adq02aa36bq82hAv3craq/d80nAdWAHGAG8IwWEoyIDAeGA8TFxSVOnTq1RImmp6dTsWLFEm3rbfwlF3/JAzyfywcbMpm/O5sXLomkepRnf7pz6nNZvj+b11dmckXDUK5vHlYmffrS/2P70nMZs+QMNaKCeKxLBOHB/zv6KW0evXv3Xq6qHX+zQlUv+AIGARPzzd8CvFGgzTqgTr75bUBsvvlWrmWN8y2Ld/2NBr4Gbi0qlsTERC2p+fPnl3hbb+MvufhLHqqez2XP0dPaavRX2nfsAj1xJsuj7+XE5/LL8TN60dPz9MrXFmrm2Zwy69fX/h/7dsMv2mDUbP3zxys0Nzf3v8tLmweQrIXsU935KrEHqJtvvo5rWaFtRCQEqAwcds3XAT5z7eD/ewyrqntcf08CH5E31GSMKUTtmEj+fXMHUg6kc88HK8jK9o57yZSF3FzloWmryTyby78GtyMsJHBPTrysZRwP/aEZn6/ay9sLUz3+fu78l14GNBWRhiISBgwGZhVoM4u8H3kh74jhe1VVEYkBvgRGqeqic41FJEREYl3TocCV5B1FGGPO45Km1Xnxurb8mHKIUTPW+M19giYt2s6PKYcYfVUCjav7xnCNJ43o3YTL29TkhbmbWLDloEffq8gCoKrZwEhgHrARmKaq60VkjIgMcDV7B6gmIinAg8C5U0VHAk2A0QVO9wwH5onIGmAVeUcQb5dhXsb4pesS6/B/fZrx6co9/OPrLU6HU2ob9p7gpa8284eEOAZ3qlv0BgFARHh50EU0i4vmvo9WsOPQKY+9l1sP01TVOcCcAstG55vOAK4vZLtngGfO022i+2EaY84Z0bsJe46d4Y35KdSKieCmLvWdDqlEMs7mcP/UlVSOCuXF69oGxCmf7qoQHsLbt3bkqjd+ZPj7yfyljWeO9gJ3sM0YHyUi/H1ga3o3r84TM9fx3cb9TodUIs/P2cjWA+n84/qLqFqhbM768Sd1q0Yx7sa8330mrs30yAOCrAAY44NCgoN448YOtI6vzMiPVjp+V8nimr/pAO/9tJNhPRrSs1l1p8PxWt2bxPLY5S1ZeSCHNXuOl3n/VgCM8VEVwkN4Z2gnYqPDGDZ5GTsPe26suCwdOJnBw9NX06JmNA/3be50OF5vWI+G/P3iSNrVjSnzvq0AGOPDqkeH897tnclVZeiknzmcnul0SBe0cd8Jrh2/mJMZ2bw6uD0RocFOh+T1RIT4aM/sqq0AGOPjGlWvyMShHdl3PIM7piRzJsuZWwsX5cs1+7h2/GLO5uTyyV3daF4z2umQAp4VAGP8QGL9qrw6uD2rdh/jz1NXkuOBHwxLKjdXeWXeZkZ8tIKWtaL5YmQPjwxnmOKzAmCMn+jXuiZPXdWKbzbs56lZztxfvqCTGWcZ/n4yb8xP4YaOdfl4eFdqVIpwOizj4tZ1AMYY3zD04gbsPXaGt35IJb5KJHf/rrFjsaQeTGf4+8vZfugUTw9oxa3d6tu5/l7GCoAxfuaRfi3YezyDF+ZuolblCAa2K/+HqiRtPsB9H68kNDiID4Z1oVvjauUegymaFQBj/ExQkPDK9W05cCKD//vPaqpHh3Nx49hyeW9V5a0fUnnxq020qFmJCbckUreqfz7S0R/YbwDG+KHwkGAm3NqRhrEVuGvKcjb94vlnCp/JyuH+qat4Ye4mLm9Tixn3dLOdv5ezAmCMn6ocGcq7t3cmKjyY299dxr7jnnvS1J5jZxj05mK+WLOXh/s2540h7YkKswEGb2cFwBg/Fh8Tybu3deZkRja3v7uMExlny/w9lqYeZsDrP7Lr8GneGdqREb2b2I+9PsIKgDF+LqF2Jd68OdH1MJnlZfYwGVXl/SU7uWniUipHhTJzZHcubRFXJn2b8mEFwJgA0KNpLC8NasuilMM8UgYPk8nKzuWxz9bxxMx19GxWnZkjutvDXHyQDdIZEyCu7VCHvcfO8MrXW6gdE8HDfVuUqJ+DJzO554PlJO88yr29GvNQn+YEB9mQjy+yAmBMAMl7mEwG4+Zvo1blSG7uWryHyaxJO8Zd7y/n6OksXh/Snqsuqu2hSE15sAJgTADJe5hMK/afyGD05+uoWSmC3ye4N27/2co0Rs1YS2zFcGbcczGtalf2cLTG0+w3AGMCTN7DZNrnPUzm4xVFPkwmOyeXZ7/cwF8+WU27ujHMGtnddv5+wgqAMQEoKizvYTI1oiMYNnnZeR88fux0FrdPXsbbC7cztFt9PrijC9UqhpdztMZTrAAYE6CqR4cz+fZO5Kpy27u/fZjMlv0nGThuEUtSD/PidW14emBrQoNtl+FP3Po0RaSfiGwWkRQRGVXI+nAR+cS1fqmINMi37lHX8s0i0tfdPo0xnpf3MJlO7DuewbD3/vcwmXnrf+GacYs4nZXD1OHduKFTPYcjNZ5QZAEQkWBgHNAfSACGiEhCgWbDgKOq2gQYC7zo2jYBGAy0AvoB40Uk2M0+jTHlILF+FV4b0p7Vace47+OVzEzJ4q73l9OkRkW+GNmDxPpVnA7ReIg7RwCdgRRVTVXVLGAqMLBAm4HAe67p6cBlknct+EBgqqpmqup2IMXVnzt9GmPKSd9WNXl6QCu+3bifmSlnua5DHT65qxs1K9vDW/yZO6eBxgO7882nAV3O10ZVs0XkOFDNtXxJgW3P3Zy8qD4BEJHhwHCAuLg4kpKS3Aj5t9LT00u8rbfxl1z8JQ/wj1zqATe3DCPnbCZ9qh9hyaKFTodUav7wuYDn8vD66wBUdQIwAaBjx47aq1evEvWTlJRESbf1Nv6Si7/kAf6TSy/8Jxfwn1w8lYc7Q0B7gLr55uu4lhXaRkRCgMrA4Qts606fxhhjPMidArAMaCoiDUUkjLwfdWcVaDMLGOqaHgR8r3l3m5oFDHadJdQQaAr87GafxhhjPKjIISDXmP5IYB4QDExS1fUiMgZIVtVZwDvA+yKSAhwhb4eOq900YAOQDYxQ1RyAwvos+/SMMcacj1u/AajqHGBOgWWj801nANefZ9tngWfd6dMYY0z5scv6jDEmQFkBMMaYAGUFwBhjApQVAGOMCVBS2meDlicROQjsLOHmscChMgzHSf6Si7/kAZaLt/KXXEqbR31VrV5woU8VgNIQkWRV7eh0HGXBX3LxlzzAcvFW/pKLp/KwISBjjAlQVgCMMSZABVIBmOB0AGXIX3LxlzzAcvFW/pKLR/IImN8AjDHG/FogHQEYY4zJxwqAMcYEqIAqACLSTkSWiMgqEUkWkc5Ox1QaInKfiGwSkfUi8pLT8ZSGiDwkIioisU7HUlIi8rLr81gjIp+JSIzTMRWHiPQTkc0ikiIio5yOp6REpK6IzBeRDa5/G/c7HVNpuZ6lvlJEZpdlvwFVAICXgKdVtR0w2jXvk0SkN3nPUb5IVVsBrzgcUomJSF2gD7DL6VhK6Rugtaq2BbYAjzocj9tEJBgYB/QHEoAhIpLgbFQllg08pKoJQFdghA/ncs79wMay7jTQCoAClVzTlYG9DsZSWvcAL6hqJoCqHnA4ntIYC/yVvM/HZ6nq16qa7ZpdQt6T7nxFZyBFVVNVNQuYSt4XDJ+jqvtUdYVr+iR5O874C2/lvUSkDnAFMLGs+w60AvAA8LKI7CbvG7PPfEMrRDPgEhFZKiILRKST0wGVhIgMBPao6mqnYyljfwLmOh1EMcQDu/PNp+HDO81zRKQB0B5Y6nAopfEv8r4g5ZZ1x17/UPjiEpFvgZqFrHocuAz4i6rOEJE/kvcks9+XZ3zFUUQuIUBV8g5xOwHTRKSReuF5vUXk8Rh5wz8+4UK5qOrnrjaPkzcM8WF5xmZ+TUQqAjOAB1T1hNPxlISIXAkcUNXlItKrzPv3wv2Fx4jIcSBGVVVEBDiuqpWK2s4bichXwIuqOt81vw3oqqoHnY3MfSLSBvgOOO1aVIe8YbnOqvqLY4GVgojcBtwFXKaqp4to7jVEpBvwlKr2dc0/CqCqzzsaWAmJSCgwG5inqv90Op6SEpHngVvI+0IRQd4Q9qeqenNZ9B9oQ0B7gd+5pi8FtjoYS2nNBHoDiEgzIAwfu+uhqq5V1Rqq2kBVG5A37NDBh3f+/cg7VB/gSzt/l2VAUxFpKCJh5D3Xe5bDMZWI68vdO8BGX975A6jqo6pax/XvYzDwfVnt/MEPh4CKcCfwqoiEABnAcIfjKY1JwCQRWQdkAUO9cfgnwLwBhAPf5O2DWKKqdzsbkntUNVtERgLzgGBgkqqudziskupO3rfmtSKyyrXsMddzyE0+ATUEZIwx5n8CbQjIGGOMixUAY4wJUFYAjDEmQFkBMMaYAGUFwBhjApQVAGOMCVBWAIwxJkD9P1oltmVF/8idAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plot_me(4, 8, d3)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-10 0.09426682072253935 1.0 0.0922928138836063\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plot_me(8, 16, d3)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-5 0.448 1.0 0.0620794555335\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plot_me(2, 5, d3)" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.448" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "get_chance(2,5,-5)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.11" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} +{ + "cells": [], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + }, + "pycharm": { + "stem_cell": { + "cell_type": "raw", + "source": [ + "dsfg\n", + "\n", + "%%\n", + "\n", + "import math\n", + "\n", + "def _get_win_chance(attack_unit, defense_unit, loss):\n", + " if attack_unit == 1 and defense_unit == 1:\n", + " return (math.comb(6, 2)) / 6 ** 2\n", + " elif attack_unit == 1 and defense_unit == 2:\n", + " return (math.comb(6, 2)) / 6 ** 3\n", + " elif attack_unit == 2 and defense_unit == 1:\n", + " return ((6 ** 3 - math.comb(6 + 1, 2)) / 6 ** 3) + \\\n", + " _get_win_chance(attack_unit - 1, defense_unit, )\n", + " elif attack_unit == 2 and defense_unit == 2:\n", + " return ((6 ** 4 - math.comb((6 ** 2) + 1, 2)) / 6 ** 4) + \\\n", + " _get_win_chance(attack_unit - 1, defense_unit - 1)\n", + " elif attack_unit == 3 and defense_unit == 1:\n", + " return ((6 ** 4 - math.comb(6 + 1, 2)) / 6 ** 4) + \\\n", + " _get_win_chance(attack_unit - 1, defense_unit)\n", + " elif attack_unit == 3 and defense_unit == 2:\n", + " if loss == -1:\n", + " return ((6 ** 5 - math.comb((6 ** 2) + 1, 2)) / 6 ** 5) + \\\n", + " _get_win_chance(attack_unit - 1, defense_unit - 1, -1) + \\\n", + " _get_win_chance(attack_unit - 2, defense_unit, -1)\n", + " elif loss == 0:\n", + " return (6 ** 5 - math.comb((6 ** 2) + 1, 2)) / 6 ** 5\n", + " else:\n", + " return _get_win_chance(attack_unit - loss, defense_unit - 2 + loss, -1)\n", + " else:\n", + " return _get_win_chance(3, 2, 0) * _get_win_chance(attack_unit, defense_unit - 2, -1) + \\\n", + " _get_win_chance(3, 2, 1) * _get_win_chance(attack_unit - 1, defense_unit - 1, -1) + \\\n", + " _get_win_chance(3, 2, 2) * _get_win_chance(attack_unit - 2, defense_unit, -1)\n", + "\n", + "\n", + "def get_win_chance(attack_unit, defense_unit):\n", + " return _get_win_chance(attack_unit, defense_unit - 2) + \\\n", + " _get_win_chance(attack_unit - 2, defense_unit) + \\\n", + " _get_win_chance(attack_unit - 1, defense_unit - 1)\n", + "\n", + "%%\n", + "for i in range(10):\n", + " for j in range(10):\n", + " print(get_win_chance(i, j))\n" + ], + "metadata": { + "collapsed": false + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/pz_risk/enjoy.py b/pz_risk/enjoy.py new file mode 100644 index 0000000..3d0ef9f --- /dev/null +++ b/pz_risk/enjoy.py @@ -0,0 +1,124 @@ +import os +import torch +import random +import numpy as np + +from risk_env import env +import training.utils as utils +from training.dvn import DVNAgent +from training.arguments import get_args +from wrappers import GraphObservationWrapper, DenseRewardWrapper, SparseRewardWrapper + +from agents.value import get_future, get_attack_dist, manual_value +from copy import deepcopy + +from utils import get_feat_adj_from_board + +import matplotlib.pyplot as plt + +from agents.sampling import SAMPLING + +COLORS = [ + 'tab:red', + 'tab:blue', + 'tab:green', + 'tab:purple', + 'tab:pink', + 'tab:cyan', +] + +critic_score = {a: [] for a in range(6)} +value_score = {a: [] for a in range(6)} + + +def render_info(mode="human"): + global critic_score + fig = plt.figure(2, figsize=(10, 5)) + plt.clf() + + ax1 = fig.add_subplot(121) + for a in range(6): + ax1.plot(critic_score[a], COLORS[a]) + ax1.set_title('Critic Score') + ax2 = fig.add_subplot(122) + for a in range(6): + ax2.plot(value_score[a], COLORS[a]) + ax2.set_title('Value Score') + plt.pause(0.001) + + +def main(): + args = get_args() + + torch.manual_seed(args.seed + 1000) + torch.cuda.manual_seed_all(args.seed + 1000) + + if args.cuda and torch.cuda.is_available() and args.cuda_deterministic: + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True + + torch.set_num_threads(1) + device = torch.device("cuda:0" if args.cuda else "cpu") + + e = env(n_agent=4, board_name='8node') + e = GraphObservationWrapper(e) + e = SparseRewardWrapper(e) + e.reset() + _, _, _, info = e.last() + n_nodes = info['nodes'] + n_agents = info['agents'] + + feat_size = e.observation_spaces['feat'].shape[0] + hidden_size = 20 + + critic = DVNAgent(n_nodes, n_agents, feat_size, hidden_size) + save_path = './mini_6/' + load = 80 + critic.load_state_dict(torch.load(args.dir)) + critic.eval() + e.reset() + state, _, _, _ = e.last() + + for agent_id in e.agent_iter(max_iter=1000): + state, _, _, info = e.last() + feat = torch.tensor(state['feat'], dtype=torch.float32, device=device).reshape(-1, n_nodes + n_agents, feat_size) + adj = torch.tensor(state['adj'], dtype=torch.float32, device=device).reshape(-1, n_nodes + n_agents, n_nodes + n_agents) + for a in e.possible_agents: + e.unwrapped.land_hist[a].append(len(e.unwrapped.board.player_nodes(a))) + e.unwrapped.unit_hist[a].append(e.unwrapped.board.player_units(a)) + e.unwrapped.place_hist[a].append(e.unwrapped.board.calc_units(a)) + critic_score[a].append(critic(feat, adj).detach().cpu().numpy()[:, n_nodes + a, 0][0]) + value_score[a].append(manual_value(e.unwrapped.board, a)) + + # make an action based on epsilon greedy action + if agent_id != 0: + task_id = state['task_id'] + action = SAMPLING[task_id](e.unwrapped.board, agent_id) + else: + # Use Model to Gather Future State per Valid Actions + action_scores = [] + deterministic, valid_actions = e.unwrapped.board.valid_actions(agent_id) + for valid_action in valid_actions: + sim = deepcopy(e.unwrapped.board) + if deterministic: + sim.step(agent_id, valid_action) + else: + dist = get_attack_dist(e.unwrapped.board, valid_action) + if len(dist): # TODO: Change to sampling + left = get_future(dist, mode='most') + sim.step(agent_id, valid_action, left) + else: + sim.step(agent_id, valid_action) + sim_feat, sim_adj = get_feat_adj_from_board(sim, agent_id, e.unwrapped.n_agents, e.unwrapped.n_grps) + sim_feat = torch.tensor(sim_feat, dtype=torch.float32, device=device).reshape(-1, n_nodes + n_agents, feat_size) + sim_adj = torch.tensor(sim_adj, dtype=torch.float32, device=device).reshape(-1, n_nodes + n_agents, n_nodes + n_agents) + action_scores.append(critic(sim_feat, sim_adj).detach().cpu().numpy()[:, n_nodes + agent_id]) + action = valid_actions[np.argmax(action_scores)] + + e.step(action) + e.render() + render_info() + + +if __name__ == "__main__": + main() diff --git a/pz_risk/evaluate.py b/pz_risk/evaluate.py new file mode 100644 index 0000000..486ce50 --- /dev/null +++ b/pz_risk/evaluate.py @@ -0,0 +1,107 @@ +import os +import torch +import random +import numpy as np + +from risk_env import env +import training.utils as utils +from training.dvn import DVNAgent +from training.arguments import get_args +from wrappers import GraphObservationWrapper + +from agents.value import get_future, get_attack_dist, manual_value +from copy import deepcopy + +from utils import get_feat_adj_from_board +from tqdm import tqdm + +from agents.sampling import SAMPLING + +COLORS = [ + 'tab:red', + 'tab:blue', + 'tab:green', + 'tab:purple', + 'tab:pink', + 'tab:cyan', +] + +critic_score = {a: [] for a in range(6)} +value_score = {a: [] for a in range(6)} + + +def main(): + args = get_args() + + torch.manual_seed(args.seed + 1000) + torch.cuda.manual_seed_all(args.seed + 1000) + + if args.cuda and torch.cuda.is_available() and args.cuda_deterministic: + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True + + torch.set_num_threads(1) + device = torch.device("cuda:0" if args.cuda else "cpu") + + e = env(n_agent=6, board_name='world') + e = GraphObservationWrapper(e) + e.reset() + _, _, _, info = e.last() + n_nodes = info['nodes'] + n_agents = info['agents'] + + feat_size = e.observation_spaces['feat'].shape[0] + hidden_size = 20 + + critic = DVNAgent(n_nodes, n_agents, feat_size, hidden_size) + critic.load_state_dict(torch.load(args.dir)) + critic.eval() + e.reset() + state, _, _, _ = e.last() + max_episode = 100 + result = [] + for _ in tqdm(range(max_episode)): + e.reset() + for agent_id in e.agent_iter(max_iter=20000): + state, _, _, info = e.last() + if len(e.unwrapped.board.player_nodes(0)) == n_nodes: + result.append(1) + break + elif len(e.unwrapped.board.player_nodes(0)) == 0: + result.append(-1) + break + # make an action based on epsilon greedy action + if agent_id != 0 or True: + task_id = state['task_id'] + action = SAMPLING[task_id](e.unwrapped.board, agent_id) + else: + # Use Model to Gather Future State per Valid Actions + action_scores = [] + deterministic, valid_actions = e.unwrapped.board.valid_actions(agent_id) + for valid_action in valid_actions: + sim = deepcopy(e.unwrapped.board) + if deterministic: + sim.step(agent_id, valid_action) + else: + dist = get_attack_dist(e.unwrapped.board, valid_action) + if len(dist): # TODO: Change to sampling + left = get_future(dist, mode='most') + sim.step(agent_id, valid_action, left) + else: + sim.step(agent_id, valid_action) + sim_feat, sim_adj = get_feat_adj_from_board(sim, agent_id, e.unwrapped.n_agents, e.unwrapped.n_grps) + sim_feat = torch.tensor(sim_feat, dtype=torch.float32, device=device).reshape(-1, + n_nodes + n_agents, + feat_size) + sim_adj = torch.tensor(sim_adj, dtype=torch.float32, device=device).reshape(-1, n_nodes + n_agents, + n_nodes + n_agents) + action_scores.append(critic(sim_feat, sim_adj).detach().cpu().numpy()[:, n_nodes + agent_id]) + action = valid_actions[np.argmax(action_scores)] + + e.step(action) + + print(sum(result), sum([r for r in result if r > 0]), sum([r for r in result if r < 0]), max_episode - len(result)) + + +if __name__ == "__main__": + main()