{ "cells": [ { "cell_type": "markdown", "id": "d3cf5102-a75e-4223-ac77-d7638661c6af", "metadata": {}, "source": [ "# SMS水面抜け" ] }, { "cell_type": "markdown", "id": "fb09a37b-e0a0-49ec-a139-8aab8634afd7", "metadata": {}, "source": [ "## 準備\n", "高速化のために[numpy](https://numpy.org/doc/stable/reference/index.html#reference)と[pytorch](https://pytorch.org/docs/stable/index.html)を使います" ] }, { "cell_type": "code", "execution_count": null, "id": "ee560598-d34e-41b1-8510-3abf0dd35d9f", "metadata": {}, "outputs": [], "source": [ "!pip install numpy torch tqdm sms-gap==0.1.0" ] }, { "cell_type": "markdown", "id": "6f3888db-40f8-4404-b61e-fa6f74984140", "metadata": {}, "source": [ "次に、必要なpackageをimportします" ] }, { "cell_type": "code", "execution_count": null, "id": "6e6e4ef0-6601-4bc1-9a12-e0c673710d0d", "metadata": {}, "outputs": [], "source": [ "# cudaを使う場合は次の命令をuncommentしてください\n", "#%set_env SMS_PYTORCH_DEVICE=cuda" ] }, { "cell_type": "code", "execution_count": 1, "id": "c11636cf-a5c8-4bf7-851c-c2461268da5d", "metadata": {}, "outputs": [], "source": [ "import time # 実行時間を計るため\n", "from tqdm.notebook import tqdm # progress bar\n", "import numpy as np\n", "import torch\n", "from itertools import combinations as combin\n", "import operator as op\n", "import logging\n", "from functools import reduce\n", "from sms.gap import find_x, find_z, find_neigh, find_all, find_in_result, verify, frange, f32, binsearch\n", "logger = logging.getLogger('SMS-gap')\n", "\n", "def hook():\n", " from memorylib import Dolphin\n", " global d, dolphin\n", " d = dolphin = Dolphin()\n", " assert dolphin.find_dolphin(), 'Dolphin not found'\n", " assert dolphin.init_shared_memory(), 'MEM1 not found'\n", " assert dolphin.read_ram(0, 3).tobytes() == b'GMS', 'Current game is not Sunshine'\n", "\n", "import struct\n", "read_struct = lambda addr, fmt: struct.unpack(fmt, d.read_ram(addr-0x80000000, struct.calcsize(fmt)))\n", "read_ptr = lambda addr: d.read_uint32(addr)" ] }, { "cell_type": "code", "execution_count": null, "id": "4a265298-e7cc-4b83-bd03-427c8529289a", "metadata": {}, "outputs": [], "source": [ "# 後からdeviceを変更したい時は次のようにpackageをreloadする必要があります\n", "## 使うdevice\n", "#%set_env SMS_PYTORCH_DEVICE=cpu\n", "#import importlib\n", "#import sms.gap\n", "#importlib.reload(sms.gap)\n", "#from sms.gap import find_x, find_z, find_neigh, find_all, find_in_result, verify, frange, f32" ] }, { "cell_type": "markdown", "id": "17755dd0-79c4-4f89-a8d0-453bc3193fc4", "metadata": {}, "source": [ "## 境界を指定" ] }, { "cell_type": "markdown", "id": "668d9d1b-01fa-46c2-9b86-727bd98580c7", "metadata": {}, "source": [ "### 方法1: 座標で指定" ] }, { "cell_type": "code", "execution_count": 2, "id": "2972ffee-a928-4d93-889f-e6d33da3092d", "metadata": {}, "outputs": [], "source": [ "bd = (\n", " (-6000, -33900),\n", " ( 6200, 32700),\n", ")" ] }, { "attachments": { "f124c718-30d3-4d16-b195-31462045b3df.png": { "image/png": "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" } }, "cell_type": "markdown", "id": "971f32c6-c0a6-45b2-a82e-acc335f0c55a", "metadata": {}, "source": [ "### 方法2: 二つの三角形の座標(hex形式)で指定\n", "[Dolphin-memory-engine](https://github.com/aldelaro5/Dolphin-memory-engine)\n", "を使う場合、次のように設定すれば水面の三角形の座標をhex形式で取得できます。\n", "\n", "![image.png](attachment:f124c718-30d3-4d16-b195-31462045b3df.png)\n", "\n", "Level 2について、 \n", "水面三角形を調べる場合は`E4`にし、 \n", "普通の床三角形を調べる場合は`E0`にします。" ] }, { "cell_type": "code", "execution_count": 3, "id": "3cc8afd9-1797-48ed-9466-9ae0090391ba", "metadata": {}, "outputs": [], "source": [ "# 三角形1のhex\n", "raw1 = 'C5 BB 80 00 00 00 00 00 C7 04 6C 00 C5 BB 80 00 00 00 00 00 46 FF 78 00 45 C1 C0 00 00 00 00 00 46 FF 78 00'" ] }, { "cell_type": "code", "execution_count": 4, "id": "c2248666-4d53-49ad-9e6e-d96fdbd2e80a", "metadata": {}, "outputs": [], "source": [ "# 三角形2のhex\n", "raw2 = 'C5 BB 80 00 00 00 00 00 C7 04 6C 00 45 C1 C0 00 00 00 00 00 46 FF 78 00 45 C1 C0 00 00 00 00 00 C7 04 6C 00'" ] }, { "cell_type": "code", "execution_count": 5, "id": "96353351-0bec-44c8-a154-8b4136369d3f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "三角形1の座標:\n", " [[ -6000. -33900.]\n", " [ -6000. 32700.]\n", " [ 6200. 32700.]]\n", "三角形2の座標:\n", " [[ -6000. -33900.]\n", " [ 6200. 32700.]\n", " [ 6200. -33900.]]\n", "\n", "境界: ((-6000.0, -33900.0), (6200.0, 32700.0))\n" ] } ], "source": [ "tri1, tri2 = (\n", " np.frombuffer(bytes.fromhex(raw), '>f').reshape(-1, 3)[:3, [0,2]]\n", " for raw in (raw1, raw2)\n", ")\n", "print('三角形1の座標:\\n', tri1)\n", "print('三角形2の座標:\\n', tri2)\n", "\n", "bds = reduce(op.__and__, (\n", " set(map(\n", " frozenset, combin(map(tuple, tri), 2)\n", " ))\n", " for tri in (tri1, tri2)\n", ")) \n", "assert len(bds)>0, '入力した三角形に共通の頂点座標がない'\n", "if len(bds)>1: logger.warning('入力した三角形に共通の頂点座標が2個以上存在する')\n", "bd = tuple(next(iter(bds)))\n", "print('\\n境界:', bd)" ] }, { "cell_type": "markdown", "id": "59c1482e-c69c-4757-8c63-c6c773ac26d4", "metadata": {}, "source": [ "### 方法3: memorylibを用いてDolphinから直接に読み込む\n", "サンシャインを起動して`hook()`を実行します" ] }, { "cell_type": "code", "execution_count": 6, "id": "212e86c8-65b1-485f-aec9-2b58d23c3587", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2932239377344 0x2aab71623c0\n" ] } ], "source": [ "hook()" ] }, { "cell_type": "markdown", "id": "5a63a7d9-78cb-4172-a159-ab6bb3ab5abc", "metadata": {}, "source": [ "調べるのは水面ならば`offset`を`0xE4`に、普通の床ならば`0xE0`にします" ] }, { "cell_type": "code", "execution_count": 7, "id": "abf3085c-0537-49d2-9cd9-7aa4ffa97bf6", "metadata": {}, "outputs": [], "source": [ "offset = 0xE4" ] }, { "cell_type": "markdown", "id": "eda9c35b-04ce-4100-8845-24bf46c1f0a5", "metadata": {}, "source": [ "Dolphinで一つ目の水面/床三角形に移動し、次の命令を実行します" ] }, { "cell_type": "code", "execution_count": 8, "id": "a59abfbf-acd8-432c-811f-874762815508", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ -6000., -33900.],\n", " [ -6000., 32700.],\n", " [ 6200., 32700.]])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tri1 = np.array(read_struct(read_ptr(read_ptr(0x8040A378)+offset)+0x10, '>9f')).reshape(3, 3)[:, [0,2]]\n", "tri1" ] }, { "cell_type": "markdown", "id": "1c3fa7be-8fb0-40bd-b812-d91145963288", "metadata": {}, "source": [ "次に、Dolphinで二つ目の水面/床三角形に移動し、次の命令を実行します" ] }, { "cell_type": "code", "execution_count": 9, "id": "d0ab10e3-1a52-4175-9453-b252b8971143", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ -6000., -33900.],\n", " [ 6200., 32700.],\n", " [ 6200., -33900.]])" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tri2 = np.array(read_struct(read_ptr(read_ptr(0x8040A378)+offset)+0x10, '>9f')).reshape(3, 3)[:, [0,2]]\n", "tri2" ] }, { "cell_type": "code", "execution_count": 10, "id": "602def54-7516-421d-a069-9f3c1f4987fa", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "境界: ((-6000.0, -33900.0), (6200.0, 32700.0))\n" ] } ], "source": [ "bds = reduce(op.__and__, (\n", " set(map(\n", " frozenset, combin(map(tuple, tri), 2)\n", " ))\n", " for tri in (tri1, tri2)\n", ")) \n", "assert len(bds)>0, '入力した三角形に共通の頂点座標がない'\n", "if len(bds)>1: logger.warning('入力した三角形に共通の頂点座標が2個以上存在する')\n", "bd = tuple(next(iter(bds)))\n", "print('境界:', bd)" ] }, { "cell_type": "markdown", "id": "adf87d26-a957-4724-a85b-58b6322ca540", "metadata": {}, "source": [ "## 探索\n", "注意:逆算の誤差によりFalse Positive/False Negativeが発生する可能性があります" ] }, { "cell_type": "markdown", "id": "ea3afb8c-7849-4897-a92a-c181f6e2c5b6", "metadata": {}, "source": [ "### 近傍の探索" ] }, { "cell_type": "code", "execution_count": 11, "id": "0b0e6e62-97e5-422b-8bb5-c1cd6599a732", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "実行時間: 0.133(秒)\n" ] } ], "source": [ "axis = 'x' # x軸に沿って探索する\n", "xC = -1000 # 探索の中心(x座標)\n", "R = 50 # 探索の半径\n", "max_count = 1e8 # 最大1億件探索する\n", "\n", "t0 = time.time()\n", "xzz, valid = find_neigh(axis, xC, 50, bd, max_count)\n", "print('実行時間: %.3f(秒)'%(time.time()-t0))" ] }, { "cell_type": "markdown", "id": "767e8380-15f3-4c93-bba6-34e714cd4182", "metadata": {}, "source": [ "#### すり抜けできるx座標の個数" ] }, { "cell_type": "code", "execution_count": 12, "id": "8cbf1362-3829-4535-bf1d-d9c033f3a622", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor(652310)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valid.sum()" ] }, { "cell_type": "markdown", "id": "5b52eaf8-9fcc-4e65-86c0-67aa1f97151c", "metadata": {}, "source": [ "#### xC=-1000を中心に最も近い10+10件を表示" ] }, { "cell_type": "code", "execution_count": 13, "id": "83547a60-8aaa-4a1e-a30d-ed79f799b515", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x\t\tz Min\t\tz Max\n", "-1000.0003\t-6604.9204\t-6604.92\n", "-1000.00037\t-6604.9204\t-6604.92\n", "-1000.0004\t-6604.9204\t-6604.92\n", "-1000.0005\t-6604.9204\t-6604.92\n", "-1000.00055\t-6604.9204\t-6604.92\n", "-1000.0006\t-6604.9204\t-6604.92\n", "-1000.0007\t-6604.9204\t-6604.92\n", "-1000.0017\t-6604.928\t-6604.9277\n", "-1000.0018\t-6604.928\t-6604.9277\n", "-1000.00183\t-6604.928\t-6604.9277\n", "\n", "x\t\tz Min\t\tz Max\n", "-999.99927\t-6604.9126\t-6604.912\n", "-999.9992\t-6604.9126\t-6604.912\n", "-999.99915\t-6604.9126\t-6604.912\n", "-999.9991\t-6604.9126\t-6604.912\n", "-999.999\t-6604.9126\t-6604.912\n", "-999.99896\t-6604.9126\t-6604.912\n", "-999.9989\t-6604.9126\t-6604.912\n", "-999.99884\t-6604.9126\t-6604.912\n", "-999.9988\t-6604.9126\t-6604.912\n", "-999.99774\t-6604.905\t-6604.9043\n" ] } ], "source": [ "idxC = binsearch(xzz[:, 0], xC)\n", "idxVC = valid[:idxC].sum()\n", "xzzV = xzz[valid]\n", "\n", "header = ('x', 'z Min', 'z Max') if axis=='x' else ('z', 'x Min', 'x Max')\n", "print(*header, sep='\\t\\t')\n", "for r in xzzV[:idxVC][-10:].flip(0).cpu().numpy():\n", " print(*r, sep='\\t')\n", "\n", "print()\n", "print(*header, sep='\\t\\t')\n", "for r in xzzV[idxVC:][:10].cpu().numpy():\n", " print(*r, sep='\\t')" ] }, { "cell_type": "markdown", "id": "2e3f3f94-4293-41ba-a948-f1948c5c91d5", "metadata": {}, "source": [ "#### 結果をcsvファイルに保存" ] }, { "cell_type": "code", "execution_count": 14, "id": "02b2dba6-e840-4397-aafc-41f4a3a82d7e", "metadata": {}, "outputs": [], "source": [ "with open('gap.csv', 'w') as fw:\n", " print(*header, sep=',', file=fw)\n", " for p in xzzV.cpu().numpy():\n", " print(*p, sep=',', file=fw)" ] }, { "cell_type": "markdown", "id": "94c1ae12-951d-4272-a60e-20e17674bfeb", "metadata": {}, "source": [ "### 全探索\n", "探索効率のために、探索の領域を二つに分けてそれぞれx軸とz軸に沿って探索することにします" ] }, { "cell_type": "code", "execution_count": 15, "id": "88400bb3-4b7d-46ac-ab44-73fd0e45d3f6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "実行時間: 14.402(秒)\n", "すり抜け可能/探索したx座標の個数: 17,028,477 / 49,272,585\n", "すり抜け可能/探索したz座標の個数: 8,641,209 / 49,622,817\n" ] } ], "source": [ "t0 = time.time()\n", "\n", "# 探索\n", "xzz, zxx = find_all(bd)\n", "# 結果\n", "xzzValid = xzz[:,1] <= xzz[:,2]\n", "zxxValid = zxx[:,1] <= zxx[:,2]\n", "xzzV = xzz[xzzValid]\n", "zxxV = zxx[zxxValid]\n", "\n", "print('実行時間: %.3f(秒)'%(time.time()-t0))\n", "print(f'すり抜け可能/探索したx座標の個数: {xzzV.shape[0]:,} / {xzz.shape[0]:,}')\n", "print(f'すり抜け可能/探索したz座標の個数: {zxxV.shape[0]:,} / {zxx.shape[0]:,}')" ] }, { "cell_type": "markdown", "id": "c450c35e-d8f8-4bf1-a549-8223152b9dce", "metadata": {}, "source": [ "例えば、コロロの水面の場合、x=197.4539\\~6199.9985まではx軸に沿って探索し、それ以外(z=-33900\\~-11320)はz軸に沿って探索します。" ] }, { "cell_type": "code", "execution_count": 16, "id": "1a0cb7bb-0bc5-4659-b998-f567e42336aa", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\t x\t\tz Min\t z Max\n", "tensor([[ 197.4539, -67.9980, -67.9971],\n", " [ 197.4539, -67.9980, -67.9971],\n", " [ 197.4539, -67.9980, -67.9971],\n", " ...,\n", " [ 6199.9966, 32699.9805, 32699.9805],\n", " [ 6199.9971, 32699.9805, 32699.9824],\n", " [ 6199.9985, 32699.9902, 32699.9902]])\n", "\t z\t\tx Min\t x Max\n", "tensor([[-3.3900e+04, -6.0000e+03, -6.0000e+03],\n", " [-3.3900e+04, -6.0000e+03, -6.0000e+03],\n", " [-3.3900e+04, -6.0000e+03, -6.0000e+03],\n", " ...,\n", " [-1.1320e+03, 2.5457e+00, 2.5461e+00],\n", " [-1.1320e+03, 2.5457e+00, 2.5461e+00],\n", " [-1.1320e+03, 2.5457e+00, 2.5461e+00]])\n" ] } ], "source": [ "print('\\t x\\t\\tz Min\\t z Max')\n", "print(xzzV)\n", "print('\\t z\\t\\tx Min\\t x Max')\n", "print(zxxV)" ] }, { "cell_type": "markdown", "id": "8c8df25d-198b-4a01-a4ca-e78b05c62e36", "metadata": {}, "source": [ "#### 結果を保存(ファイルサイズが大きいので注意!)" ] }, { "cell_type": "code", "execution_count": 17, "id": "64b5b5e1-bc2e-4963-a91f-b397f45065af", "metadata": {}, "outputs": [], "source": [ "torch.save((xzzV, zxxV), 'result.pt')" ] }, { "cell_type": "code", "execution_count": 18, "id": "525c997b-04c8-405c-8890-3c3cd61ec286", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-rw-r--r-- 1 sup39 None 294M Jun 17 16:28 result.pt\n" ] } ], "source": [ "!ls -lh result.pt\n", "# コロロの水面抜け可能座標をファイルに保存すると294MBなります" ] }, { "cell_type": "markdown", "id": "9b65254d-290c-4efa-9c70-e20614e99d11", "metadata": {}, "source": [ "#### 結果をcsvファイルに保存\n", "ファイルが非常に大きくなるのでおすすめしません!\n", "\n", "例えばコロロの水面の場合、合計約750MBになりました。\n", "ファイルサイズが大きすぎてExcelなどでは開けない可能性が高いので、\n", "保存するとしたら`torch.save()`を使うことをおすすめします。" ] }, { "cell_type": "code", "execution_count": null, "id": "a351ba22-7127-4eee-8d47-b76441fcd7e8", "metadata": {}, "outputs": [], "source": [ "for sfx, rsfx, a in zip('xz', 'zx', (xzzV, zxxV)):\n", " with open(f'result-{sfx}.csv', 'w') as fw:\n", " print(sfx, rsfx+' Min', rsfx+' Max', sep=',', file=fw)\n", " for p in tqdm(a.cpu().numpy()):\n", " print(*p, sep=',', file=fw)" ] }, { "cell_type": "markdown", "id": "bef3029d-7ee3-4942-8a78-ba9bbf90c915", "metadata": {}, "source": [ "#### 全探索の結果で調べる" ] }, { "cell_type": "code", "execution_count": 19, "id": "0f074fcb-e8f5-46e4-9c7b-ab84de096d80", "metadata": {}, "outputs": [], "source": [ "# 保存した結果を読み込む\n", "xzzV, zxxV = torch.load('result.pt')" ] }, { "cell_type": "markdown", "id": "5cad741f-da63-42b6-aa9f-0ad2d27ab746", "metadata": {}, "source": [ "##### 特定のx座標" ] }, { "cell_type": "code", "execution_count": 20, "id": "e85c9f26-21e8-4de3-bf7f-d4b0c5a7ffca", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([[-1000.0004, -6604.9204, -6604.9199]])" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "find_in_result('x', f32(-1000.00037), xzzV, zxxV)\n", "# x, z Min, z Max" ] }, { "cell_type": "markdown", "id": "23cd14d8-19f7-4b58-b4e6-b7d48c5afaec", "metadata": {}, "source": [ "##### 特定のz座標" ] }, { "cell_type": "code", "execution_count": 21, "id": "cf5fcdf5-a093-44f6-94c2-2f80ee52877e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([[-6604.9204, -1000.0007, -1000.0003]])" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "find_in_result('z', -6604.9204, xzzV, zxxV)\n", "# z, x Min, x Max" ] }, { "cell_type": "code", "execution_count": 22, "id": "e0d500a7-a75c-4aaf-a67d-356d2e10196c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([], size=(0, 3))" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 何も返さなかったら該当なし\n", "find_in_result('z', -6604, xzzV, zxxV)" ] }, { "cell_type": "markdown", "id": "990345d9-f2eb-484b-b3a6-d8e64d4a725d", "metadata": {}, "source": [ "##### 近傍での探索" ] }, { "cell_type": "code", "execution_count": 23, "id": "85e8bc03-21cd-49e9-9cb7-cafb1971efa0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([[ 950.0003, 4040.1663, 4040.1667],\n", " [ 950.0004, 4040.1663, 4040.1667],\n", " [ 950.0004, 4040.1663, 4040.1667],\n", " ...,\n", " [1049.9994, 4586.0605, 4586.0610],\n", " [1049.9995, 4586.0605, 4586.0610],\n", " [1049.9996, 4586.0605, 4586.0610]])" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "find_in_result('x', frange(950, 1050), xzzV, zxxV)" ] }, { "cell_type": "code", "execution_count": 24, "id": "40aac4c5-a26f-4d42-a408-6c2e39c41053", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([[ 950.0059, 383.9348, 383.9353],\n", " [ 950.0059, 383.9348, 383.9353],\n", " [ 950.0060, 383.9348, 383.9353],\n", " ...,\n", " [1049.9987, 402.2517, 402.2522],\n", " [1049.9988, 402.2517, 402.2522],\n", " [1049.9989, 402.2517, 402.2522]])" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "r = find_in_result('z', frange(950, 1050), xzzV, zxxV)\n", "r" ] }, { "cell_type": "markdown", "id": "c2d819b6-5c84-4af4-b29d-256ff11c5633", "metadata": {}, "source": [ "##### 結果をcsv形式でexport" ] }, { "cell_type": "code", "execution_count": 25, "id": "3ee934fe-262f-44b0-ba5f-1a275a77e826", "metadata": {}, "outputs": [], "source": [ "axis = 'z'\n", "\n", "header = ('x', 'z Min', 'z Max') if axis=='x' else ('z', 'x Min', 'x Max')\n", "with open('gap.csv', 'w') as fw:\n", " print(*header, sep=',', file=fw)\n", " for p in r.cpu().numpy():\n", " print(*p, sep=',', file=fw)" ] }, { "cell_type": "code", "execution_count": null, "id": "e6ac3de6-9487-42dd-8d49-92a7ba77e5b5", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "bc3d0d67-9534-4e1f-b08a-ee452c59f93e", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "b746ed07-0ce1-4859-8e0c-1ab3b1bd2056", "metadata": {}, "source": [ "## LICENSE" ] }, { "cell_type": "raw", "id": "37eb0a0d-4c0a-4eb6-b55e-2fc8048b6682", "metadata": {}, "source": [ "Copyright (c) 2022 sup39[サポミク]\n", "\n", "Permission is hereby granted, free of charge, to any person\n", "obtaining a copy of this software and associated documentation\n", "files (the \"Software\"), to deal in the Software without\n", "restriction, including without limitation the rights to use,\n", "copy, modify, merge, publish, distribute, sublicense, and/or sell\n", "copies of the Software, and to permit persons to whom the\n", "Software is furnished to do so, subject to the following\n", "conditions:\n", "\n", "The above copyright notice and this permission notice shall be\n", "included in all copies or substantial portions of the Software.\n", "\n", "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n", "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n", "OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n", "HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n", "WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n", "FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n", "OTHER DEALINGS IN THE SOFTWARE." ] }, { "cell_type": "code", "execution_count": null, "id": "f7ef093f-0100-4c55-be94-26727769e189", "metadata": {}, "outputs": [], "source": [] } ], "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.9.7" } }, "nbformat": 4, "nbformat_minor": 5 }