Last active
January 16, 2024 10:18
-
-
Save FrankRuns/72e38aaba7b4c66668e5959c22cb73aa to your computer and use it in GitHub Desktop.
Python sim for the card Uno
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "A pretty ugly notebook to simulate games of the card game Uno." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 26, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "import random\n", | |
| "import pandas as pd\n", | |
| "import numpy as np\n", | |
| "import math\n", | |
| "from matplotlib import pyplot as plt" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Setup" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Create the deck" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def create_reds():\n", | |
| " reds = []\n", | |
| " for j in [1,2]:\n", | |
| " for i in range(1,10):\n", | |
| " reds.append('R_' + str(i)) \n", | |
| " reds.append('R_0')\n", | |
| " return reds\n", | |
| "\n", | |
| "def create_blues():\n", | |
| " blues = []\n", | |
| " for j in [1,2]:\n", | |
| " for i in range(1,10):\n", | |
| " blues.append('B_' + str(i)) \n", | |
| " blues.append('B_0')\n", | |
| " return blues\n", | |
| "\n", | |
| "def create_greens():\n", | |
| " greens = []\n", | |
| " for j in [1,2]:\n", | |
| " for i in range(1,10):\n", | |
| " greens.append('G_' + str(i)) \n", | |
| " greens.append('G_0')\n", | |
| " return greens\n", | |
| "\n", | |
| "def create_yellows():\n", | |
| " yellows = []\n", | |
| " for j in [1,2]:\n", | |
| " for i in range(1,10):\n", | |
| " yellows.append('Y_' + str(i)) \n", | |
| " yellows.append('Y_0')\n", | |
| " return yellows\n", | |
| "\n", | |
| "def create_draw_twos():\n", | |
| " return ['R_dt', 'B_dt', 'Y_dt', 'G_dt', 'R_dt', 'B_dt', 'Y_dt', 'G_dt']\n", | |
| "\n", | |
| "def create_skips():\n", | |
| " return ['R_sk', 'B_sk', 'Y_sk', 'G_sk', 'R_sk', 'B_sk', 'Y_sk', 'G_sk']\n", | |
| "\n", | |
| "def create_reverses():\n", | |
| " return ['R_re', 'B_re', 'Y_re', 'G_re', 'R_re', 'B_re', 'Y_re', 'G_re']\n", | |
| "\n", | |
| "def create_wild_regs():\n", | |
| " return ['w_r', 'w_r', 'w_r', 'w_r']\n", | |
| "\n", | |
| "def create_wild_draw_4s():\n", | |
| " return ['w_d4', 'w_d4', 'w_d4', 'w_d4']\n", | |
| "\n", | |
| "def create_deck():\n", | |
| " reds = create_reds() * 2\n", | |
| " blues = create_blues() * 2\n", | |
| " greens = create_greens() * 2\n", | |
| " yellows = create_yellows() * 2\n", | |
| " draw_twos = create_draw_twos() * 2\n", | |
| " skips = create_skips() * 2\n", | |
| " reverses = create_reverses() * 2\n", | |
| " wilds_reg = create_wild_regs() * 2\n", | |
| " wilds_draw = create_wild_draw_4s() * 2\n", | |
| " deck = reds + blues + yellows + greens + draw_twos + skips + reverses + wilds_reg + wilds_draw\n", | |
| " return deck" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "deck = create_deck()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "All good.\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# does it work?\n", | |
| "if len(deck) == 108 * 2:\n", | |
| " print('All good.')\n", | |
| "else: \n", | |
| " print('SOMETHING IS WRONG.')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Initialize the game giving each player cards (4-players hard coded)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 7, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def initialize_hands(deck):\n", | |
| " \n", | |
| " players = {\n", | |
| " 'player_1':[],\n", | |
| " 'player_2':[],\n", | |
| " 'player_3':[],\n", | |
| " 'player_4':[]\n", | |
| " }\n", | |
| " \n", | |
| " import random\n", | |
| "\n", | |
| " for i in range(1, 8):\n", | |
| " for key in players:\n", | |
| " pick = deck.pop(random.randint(0,len(deck)-1))\n", | |
| " players[key].append(pick)\n", | |
| " \n", | |
| " return players" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 8, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "players = initialize_hands(deck)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 9, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "All good.\n", | |
| "All good.\n", | |
| "All good.\n", | |
| "All good.\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# does it work?\n", | |
| "for key in players:\n", | |
| " if len(players[key]) == 7:\n", | |
| " print('All good.')\n", | |
| " else:\n", | |
| " print('SOMETHING IS WRONG.')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Create order of play (both forward and backwards)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 10, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "['player_1', 'player_2', 'player_3', 'player_4']\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "forward_order = list(players.keys())\n", | |
| "print(forward_order)\n", | |
| "reverse_order = forward_order[::-1]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 11, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "All good.\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# does it work?\n", | |
| "if forward_order[0] == reverse_order[3]:\n", | |
| " print('All good.')\n", | |
| "else:\n", | |
| " print('SOMETHING IS WRONG.')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Choose the initial card" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 12, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def choose_initial_card(deck):\n", | |
| " initial_card = deck.pop(random.randint(0,len(deck)-1))\n", | |
| " if initial_card not in create_draw_twos() + create_skips() + create_reverses() + create_wild_regs() + create_wild_draw_4s():\n", | |
| " return initial_card\n", | |
| " else:\n", | |
| " return choose_initial_card(deck)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 13, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "initial_card = choose_initial_card(deck)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 14, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "All good.\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# does it work? initial card shouldn't be action card (according to rule book)...\n", | |
| "if initial_card.split('_')[0] in ['R','G','B','Y'] and initial_card.split('_')[1] in ['0','1','2','3','4','5','6','7','8','9']:\n", | |
| " print('All good.')\n", | |
| "else:\n", | |
| " print('SOMETHING IS WRONG.')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Define player's action based on card at play and the players hand" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 15, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def player_action(card_at_play, player, action_color, deck):\n", | |
| " '''\n", | |
| " card_at_play (str): current card to be played\n", | |
| " player (str): player at turn\n", | |
| " '''\n", | |
| "\n", | |
| " temp_options = []\n", | |
| " \n", | |
| " # if card is not action card\n", | |
| " if card_at_play in create_reds() + create_blues() + create_greens() + create_yellows():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == card_at_play.split('_')[0] or card.split('_')[1] == card_at_play.split('_')[1] or card.split('_')[0] == 'w':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # if card is action card\n", | |
| " \n", | |
| " # if card is wild card (regular and draw 4)\n", | |
| " if card_at_play in create_wild_regs() or card_at_play in create_wild_draw_4s():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == action_color or card.split('_')[0] == 'w':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # if card is reverse\n", | |
| " if card_at_play in create_reverses():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == card_at_play.split('_')[0] or card.split('_')[0] == 'w' or card.split('_')[1] == 're':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # if card is skip\n", | |
| " if card_at_play in create_skips():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == card_at_play.split('_')[0] or card.split('_')[0] == 'w' or card.split('_')[1] == 'sk':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # if card is draw 2\n", | |
| " if card_at_play in create_draw_twos():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == card_at_play.split('_')[0] or card.split('_')[0] == 'w' or card.split('_')[1] == 'dt':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # determine move, either draw or play\n", | |
| " if len(temp_options) == 0:\n", | |
| " # print('no cards can be played, draw card from deck.')\n", | |
| " new_card = deck.pop(random.randint(0,len(deck)-1))\n", | |
| " players[player].append(new_card)\n", | |
| " pick = card_at_play\n", | |
| " card_reset = 0\n", | |
| " else:\n", | |
| " # print('cards can be played, choose randomly.')\n", | |
| " pick = random.choice(temp_options)\n", | |
| " players[player].remove(pick)\n", | |
| " card_reset = 1\n", | |
| " \n", | |
| " return {'pick':pick, 'card_reset':card_reset}\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Potential strategy action: what if player always plays action card if available?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 16, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def player_strategy(card_at_play, player, action_color, deck):\n", | |
| " '''\n", | |
| " card_at_play (str): current card to be played\n", | |
| " player (str): player at turn\n", | |
| " '''\n", | |
| "\n", | |
| " temp_options = []\n", | |
| " \n", | |
| " # if card is not action card\n", | |
| " if card_at_play in create_reds() + create_blues() + create_greens() + create_yellows():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == card_at_play.split('_')[0] or card.split('_')[1] == card_at_play.split('_')[1] or card.split('_')[0] == 'w':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # if card is action card\n", | |
| " \n", | |
| " # if card is wild card (regular and draw 4)\n", | |
| " if card_at_play in create_wild_regs() or card_at_play in create_wild_draw_4s():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == action_color or card.split('_')[0] == 'w':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # if card is reverse\n", | |
| " if card_at_play in create_reverses():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == card_at_play.split('_')[0] or card.split('_')[0] == 'w' or card.split('_')[1] == 're':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # if card is skip\n", | |
| " if card_at_play in create_skips():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == card_at_play.split('_')[0] or card.split('_')[0] == 'w' or card.split('_')[1] == 'sk':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # if card is draw 2\n", | |
| " if card_at_play in create_draw_twos():\n", | |
| " for card in players[player]:\n", | |
| " if card.split('_')[0] == card_at_play.split('_')[0] or card.split('_')[0] == 'w' or card.split('_')[1] == 'dt':\n", | |
| " temp_options.append(card) \n", | |
| " \n", | |
| " # determine move, either draw or play\n", | |
| " if len(temp_options) == 0:\n", | |
| " # print('no cards can be played, draw card from deck.')\n", | |
| " new_card = deck.pop(random.randint(0,len(deck)-1))\n", | |
| " players[player].append(new_card)\n", | |
| " pick = card_at_play\n", | |
| " card_reset = 0\n", | |
| " else:\n", | |
| " # print('cards can be played, choose randomly.')\n", | |
| " action_cards = create_wild_regs() + create_wild_draw_4s() + create_reverses() + create_skips() + create_draw_twos()\n", | |
| " action_options = [x for x in temp_options if x in action_cards]\n", | |
| " if len(action_options) > 0:\n", | |
| " pick = random.choice(action_options)\n", | |
| " else:\n", | |
| " pick = random.choice(temp_options)\n", | |
| " players[player].remove(pick)\n", | |
| " card_reset = 1\n", | |
| " \n", | |
| " return {'pick':pick, 'card_reset':card_reset}" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 17, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "{'player_1': ['w_d4', 'B_6', 'w_r', 'G_8', 'G_3', 'R_re', 'w_d4'],\n", | |
| " 'player_2': ['G_re', 'R_sk', 'B_6', 'R_6', 'G_sk', 'B_2', 'w_r'],\n", | |
| " 'player_3': ['G_8', 'B_6', 'B_sk', 'G_3', 'G_6', 'B_re', 'R_1'],\n", | |
| " 'player_4': ['G_3', 'B_3', 'Y_5', 'w_d4', 'R_3', 'Y_re', 'Y_7']}" | |
| ] | |
| }, | |
| "execution_count": 17, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "# check players hands\n", | |
| "players" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Based on card played, identify next player" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 18, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# I need a function that determines who is playing\n", | |
| "def identify_player(current_order, current_player, current_card, card_reset):\n", | |
| "\n", | |
| " if current_order == 'f':\n", | |
| " if current_card.split('_')[1] == 'sk' and card_reset == 1:\n", | |
| " if current_player == 'player_1':\n", | |
| " next_player = 'player_3'\n", | |
| " elif current_player == 'player_2':\n", | |
| " next_player = 'player_4'\n", | |
| " elif current_player == 'player_3':\n", | |
| " next_player = 'player_1'\n", | |
| " else:\n", | |
| " next_player = 'player_2'\n", | |
| " else:\n", | |
| " next_player = forward_order.index(current_player) + 1\n", | |
| " if next_player > len(forward_order) - 1:\n", | |
| " next_player = forward_order[0]\n", | |
| " else:\n", | |
| " next_player = forward_order[next_player] \n", | |
| "\n", | |
| " else: \n", | |
| " if current_card.split('_')[1] == 'sk' and card_reset == 1:\n", | |
| " if current_player == 'player_1':\n", | |
| " next_player = 'player_3'\n", | |
| " elif current_player == 'player_2':\n", | |
| " next_player = 'player_4'\n", | |
| " elif current_player == 'player_3':\n", | |
| " next_player = 'player_1'\n", | |
| " else:\n", | |
| " next_player = 'player_2'\n", | |
| " else:\n", | |
| " next_player = reverse_order.index(current_player) + 1\n", | |
| " if next_player > len(reverse_order) - 1:\n", | |
| " next_player = reverse_order[0]\n", | |
| " else:\n", | |
| " next_player = reverse_order[next_player]\n", | |
| " \n", | |
| " # print(f'The next player is {next_player}.')\n", | |
| " return next_player\n", | |
| " " | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 19, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "All good.\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# does it work?\n", | |
| "if identify_player('f', 'player_4', 'G_dt', 0) == 'player_1':\n", | |
| " print('All good.')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Based on card playerd, identify if order of play has switched" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 21, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def identify_order(current_card, card_reset, current_order):\n", | |
| " if card_reset == 0:\n", | |
| " current_order = current_order\n", | |
| " else:\n", | |
| " if current_card.split('_')[1] == 're':\n", | |
| " if current_order == 'f':\n", | |
| " current_order = 'r'\n", | |
| " # print('The order has been reveresed from f to r')\n", | |
| " else:\n", | |
| " current_order = 'f'\n", | |
| " # print('The order has been reveresed from r to f')\n", | |
| " \n", | |
| " return current_order" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### When 'draw' card is played, next player must draw cards" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 22, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def execute_card_draw(how_many, current_order, current_player, deck):\n", | |
| "\n", | |
| " '''\n", | |
| " function to figure out which player draws and how many cards to draw\n", | |
| " '''\n", | |
| " \n", | |
| " if current_order == 'f':\n", | |
| " drawing_player = forward_order.index(current_player) + 1\n", | |
| " if drawing_player > len(forward_order) - 1:\n", | |
| " drawing_player = forward_order[0]\n", | |
| " for i in range(1,how_many+1):\n", | |
| " players[drawing_player].append(deck.pop(random.randint(0,len(deck)-1)))\n", | |
| " else:\n", | |
| " drawing_player = forward_order[drawing_player]\n", | |
| " for i in range(1,how_many+1):\n", | |
| " players[drawing_player].append(deck.pop(random.randint(0,len(deck)-1)))\n", | |
| " else:\n", | |
| " drawing_player = reverse_order.index(current_player) + 1\n", | |
| " if drawing_player > len(reverse_order) - 1:\n", | |
| " drawing_player = reverse_order[0]\n", | |
| " for i in range(1,how_many+1):\n", | |
| " players[drawing_player].append(deck.pop(random.randint(0,len(deck)-1)))\n", | |
| " else:\n", | |
| " drawing_player = reverse_order[drawing_player]\n", | |
| " for i in range(1,how_many+1):\n", | |
| " players[drawing_player].append(deck.pop(random.randint(0,len(deck)-1)))\n", | |
| " \n", | |
| " return [drawing_player, how_many]\n", | |
| " " | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 23, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "All good.\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# does it work?\n", | |
| "if execute_card_draw(4, 'r', 'player_4', deck)[0] == 'player_3':\n", | |
| " print('All good.')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Run Simulations" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Single game (for testing)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 24, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# # start by doing 100 runs\n", | |
| "\n", | |
| "# print('------------------------------------ INITIALIZE GAME')\n", | |
| "\n", | |
| "# # initialize deck\n", | |
| "# deck = create_deck()\n", | |
| "\n", | |
| "# # check for a full deck\n", | |
| "# # print(deck)\n", | |
| "\n", | |
| "# # initialize player's hands\n", | |
| "# players = initialize_hands(deck)\n", | |
| "\n", | |
| "# # pick first card\n", | |
| "# current_card = choose_initial_card(deck)\n", | |
| "# print('Initial card = ', current_card)\n", | |
| "\n", | |
| "# # define first player\n", | |
| "# current_player = 'player_1'\n", | |
| "# current_order = 'f' # for forward\n", | |
| "# print('Initial player = ', current_player)\n", | |
| "# print('Initial order = ', current_order)\n", | |
| "\n", | |
| "# # initialize wild color\n", | |
| "# action_color = None\n", | |
| "\n", | |
| "# # execute first player action\n", | |
| "\n", | |
| "# print('------------------------------------ EXECUTE 1st PLAY!')\n", | |
| "\n", | |
| "# current_card = player_action(current_card, current_player, action_color, deck)\n", | |
| "# print(f'The first card that is played is {current_card}.')\n", | |
| "# current_order = identify_order(current_card['pick'], current_card['card_reset'], current_order)\n", | |
| "# current_player = identify_player(current_order, current_player, current_card['pick'], current_card['card_reset'])\n", | |
| "\n", | |
| "# print('------------------------------------ GAME ON!')\n", | |
| "\n", | |
| "# # game on! \n", | |
| "# for i in range(1,200):\n", | |
| " \n", | |
| "# # current player determines an action\n", | |
| "# current_card = player_action(current_card['pick'], current_player, action_color, deck)\n", | |
| "# print(f'The card that is played is {current_card}.')\n", | |
| " \n", | |
| "# # determine is there is a winner, else play on\n", | |
| "# if len(players[current_player]) == 0:\n", | |
| "# print(f'Game over. Player, {current_player} wins!')\n", | |
| "# break\n", | |
| " \n", | |
| "# print('Game continues.')\n", | |
| " \n", | |
| "# # what if the current card is regular wild?\n", | |
| "# if current_card['pick'].split('_')[0] == 'w':\n", | |
| "# action_color = random.choice(['B','Y','R','G'])\n", | |
| "# else:\n", | |
| "# action_color = None\n", | |
| " \n", | |
| "# # what if the current card is draw 4 wild?\n", | |
| "# if current_card['pick'].split('_')[1] == 'd4':\n", | |
| "# execute_card_draw(4, current_order, current_player, deck)\n", | |
| "\n", | |
| "# # what if the current card is draw 2? \n", | |
| "# if current_card['pick'].split('_')[1] == 'dt':\n", | |
| "# execute_card_draw(4, current_order, current_player, deck)\n", | |
| " \n", | |
| "# # based on card played (or not played), determine who is next (includes when current card is reverse)\n", | |
| "# current_order = identify_order(current_card['pick'], current_card['card_reset'], current_order)\n", | |
| " \n", | |
| "# # based on play order, determine the next player \n", | |
| "# current_player = identify_player(current_order, current_player, current_card['pick'], current_card['card_reset'])\n", | |
| " \n", | |
| "# if len(deck) < 1:\n", | |
| "# print('Game is a draw - out of cards.')\n", | |
| "# break\n", | |
| " \n", | |
| "# print(f'The current order after round {i} is ', current_order)\n", | |
| "# print(f'The player hands after round {i} is ',players)\n", | |
| "# print('---------------')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Many Games" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 25, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "Done\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "turns_1 = [] # will count how many turns or how many draw 2's this player gets\n", | |
| "turns_2 = []\n", | |
| "turns_3 = []\n", | |
| "turns_4 = []\n", | |
| "winners = [] # will store the winner of the game\n", | |
| "round_counts = [] # will count the number of turns in a game\n", | |
| "\n", | |
| "for j in range(1, 50000):\n", | |
| "\n", | |
| " t1 = 0\n", | |
| " t2 = 0\n", | |
| " t3 = 0\n", | |
| " t4 = 0\n", | |
| " winner = None\n", | |
| "\n", | |
| " # initialize deck\n", | |
| " sim_deck = create_deck()\n", | |
| "\n", | |
| " # initialize player's hands\n", | |
| " players = initialize_hands(sim_deck)\n", | |
| "\n", | |
| " # pick first card\n", | |
| " current_card = choose_initial_card(sim_deck)\n", | |
| " \n", | |
| " # define first player\n", | |
| " current_player = 'player_1'\n", | |
| " current_order = 'f' # for forward\n", | |
| "\n", | |
| " # initialize wild color\n", | |
| " action_color = None\n", | |
| "\n", | |
| " # execute first player action\n", | |
| "\n", | |
| " current_card = player_action(current_card, current_player, action_color, sim_deck)\n", | |
| " \n", | |
| " if current_card['pick'].split('_')[0] == 'w':\n", | |
| " action_color = random.choice(['B','Y','R','G'])\n", | |
| " else:\n", | |
| " action_color = None\n", | |
| " # what if the current card is draw 4 wild?\n", | |
| " if current_card['pick'].split('_')[1] == 'd4':\n", | |
| " execute_card_draw(4, current_order, current_player, sim_deck)\n", | |
| " # what if the current card is draw 2? \n", | |
| " if current_card['pick'].split('_')[1] == 'dt':\n", | |
| " execute_card_draw(2, current_order, current_player, sim_deck) \n", | |
| "\n", | |
| " current_order = identify_order(current_card['pick'], current_card['card_reset'], current_order)\n", | |
| " current_player = identify_player(current_order, current_player, current_card['pick'], current_card['card_reset'])\n", | |
| "\n", | |
| " # game on! \n", | |
| " count = 0\n", | |
| " for i in range(1,188):\n", | |
| "\n", | |
| " # current player determines an action\n", | |
| " current_card = player_action(current_card['pick'], current_player, action_color, sim_deck)\n", | |
| "# if current_player == 'player_4':\n", | |
| "# current_card = player_strategy(current_card['pick'], current_player, action_color, sim_deck)\n", | |
| "# else:\n", | |
| "# current_card = player_action(current_card['pick'], current_player, action_color, sim_deck)\n", | |
| "\n", | |
| " if current_player == 'player_1' and current_card['pick'].split('_')[1] in ['dt', 'd4']:\n", | |
| " t1 += 1\n", | |
| " if current_player == 'player_2' and current_card['pick'].split('_')[1] in ['dt', 'd4']:\n", | |
| " t2 += 1\n", | |
| " if current_player == 'player_3' and current_card['pick'].split('_')[1] in ['dt', 'd4']:\n", | |
| " t3 += 1\n", | |
| " if current_player == 'player_4' and current_card['pick'].split('_')[1] in ['dt', 'd4']:\n", | |
| " t4 += 1\n", | |
| " \n", | |
| " # determine is there is a winner, else play on\n", | |
| " if len(players[current_player]) == 0:\n", | |
| " winner = current_player\n", | |
| " winners.append(winner)\n", | |
| " break\n", | |
| "\n", | |
| " if len(sim_deck) < 1:\n", | |
| " print('Game is a draw - out of cards.')\n", | |
| " winner = 'draw'\n", | |
| " break\n", | |
| " \n", | |
| " # what if the current card is regular wild?\n", | |
| " if current_card['pick'].split('_')[0] == 'w':\n", | |
| " action_color = random.choice(['B','Y','R','G'])\n", | |
| " else:\n", | |
| " action_color = None\n", | |
| "\n", | |
| " # what if the current card is draw 4 wild?\n", | |
| " if current_card['pick'].split('_')[1] == 'd4':\n", | |
| " execute_card_draw(4, current_order, current_player, sim_deck)\n", | |
| "\n", | |
| " # what if the current card is draw 2? \n", | |
| " if current_card['pick'].split('_')[1] == 'dt':\n", | |
| " execute_card_draw(2, current_order, current_player, sim_deck)\n", | |
| "\n", | |
| " # based on card played (or not played), determine who is next (includes when current card is reverse)\n", | |
| " current_order = identify_order(current_card['pick'], current_card['card_reset'], current_order)\n", | |
| "\n", | |
| " # based on play order, determine the next player \n", | |
| " current_player = identify_player(current_order, current_player, current_card['pick'], current_card['card_reset'])\n", | |
| " \n", | |
| " count += 1\n", | |
| " \n", | |
| " round_counts.append(count)\n", | |
| " turns_1.append(t1)\n", | |
| " turns_2.append(t2)\n", | |
| " turns_3.append(t3)\n", | |
| " turns_4.append(t4) \n", | |
| " \n", | |
| "print('Done')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Analyzing and visualizing many games results" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 27, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "49519\n", | |
| "Counter({'player_1': 13364, 'player_2': 12271, 'player_3': 11987, 'player_4': 11897})\n", | |
| "[('player_2', 24.78038732607686), ('player_4', 24.02512167046992), ('player_1', 26.98762091318484), ('player_3', 24.20687009026838)]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# how many wins does each player have?\n", | |
| "from collections import Counter\n", | |
| "print(len(winners))\n", | |
| "types_counts=Counter(winners)\n", | |
| "print(types_counts)\n", | |
| "print([(i, types_counts[i] / len(winners) * 100.0) for i in types_counts])" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 28, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "<AxesSubplot:title={'center':'Win Dist Over 50k Games'}, xlabel='Player'>" | |
| ] | |
| }, | |
| "execution_count": 28, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| }, | |
| { | |
| "data": { | |
| "image/png": "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Fy9ezFVXXcXRRx/NSSed1OrtRgSnnHIK06ZNY+7cuQAsXbqUdevWccghh1T2Ysq455576N27NxMnTixkfd5DMLNd1qRJk975hL18+XJGjRpFnz59eOmll9iyZQsrVqzgiCOOYPbs2VxwwQUAnH322Xz1q19l4sSJvP/97+fmm2/eYb133303u+++O+eee+47tTFjxvDhD3+YiODiiy9m1KhRHHbYYcybNw/I3txPPPHEd5a/4IILmD17NgBDhw7lsssu48gjj+Swww7jqaeeYtWqVfz4xz/myiuvZMyYMdx/f9mfHW8T7yGY2S7rgAMOoHv37qxevZrFixdzzDHH8Nxzz7FkyRL69evH6NGjed/7dvxZ7rVr17Jo0SKeeuopTjrpJE499dT3zH/iiScYO3Zs2W3ecsstLF26lMcff5yNGzdy1FFHceyxx7bY14EDB/Loo48yc+ZMfvCDH3Dttddy7rnn0rt3by666KLKBqCE9xDMbJfWuJfQGAjHHHPMO8+bOhRz8skns9tuuzFixAjWrVvXpu0tWrSIM844g27durHvvvvykY98hIcffrjFdp/97GcBGDt2LKtWrWrTNlvLgWBmu7SJEyeyePFili1bxqhRo5gwYQJLlixh8eLFTJo0qWybHj16vDNd7su9I0eO5JFHHinbtqkvA3fv3p3t27e/87z0ktHGbXbr1o2tW7c2/6Iq5EAws13apEmTuP322+nfvz/dunWjf//+vPzyyyxZsoRjjjmmonUed9xxbNmyhZ/+9Kfv1B5++GHuvfdejj32WObNm8e2bdvYsGED9913H+PHj+eggw7iySefZMuWLbzyyissXLiwxe306dOHzZs3V9THchwIZrZLO+yww9i4cSMTJkx4T61fv34MHDiwmZZNk8Stt97KnXfeycEHH8zIkSO5/PLLOeCAAzjllFMYPXo0hx9+OMcddxzf//732W+//RgyZAinn346o0eP5swzz+SII45ocTuf+cxnuPXWWws7qex7GeX4slOzzrVixQo+9KEPVbsbXVa58W3uXkbeQzAzM8CBYGZmiQPBzMwAB4KZVVmtnsfc2VUyrg4EM6uanj17smnTJodCwRp/D6Fnz55taudbV5hZ1dTV1dHQ0MCGDRuq3ZUup/EX09rCgWBmVbP77ru36Re9rGP5kJGZmQEOBDMzS3zIyDqMv/lt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\n", | |
| "text/plain": [ | |
| "<Figure size 432x288 with 1 Axes>" | |
| ] | |
| }, | |
| "metadata": { | |
| "needs_background": "light" | |
| }, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "# visualize player wins\n", | |
| "data = pd.DataFrame.from_dict(types_counts, orient='index').reset_index()\n", | |
| "data = data.sort_values(by='index')\n", | |
| "data.columns = ['Player', 'Win Count']\n", | |
| "data.plot.bar(x='Player', y='Win Count', title='Win Dist Over 50k Games')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 37, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "1.4273885477709554\n", | |
| "1.5499509990199805\n", | |
| "1.5303306066121323\n", | |
| "1.5055901118022361\n", | |
| "-----\n", | |
| "Avg. of not player_1:\n", | |
| "1.5286239058114497\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# this is the average of how many times per game a player was hit with a draw 2 or draw 4 card...\n", | |
| "import numpy as np\n", | |
| "print(np.mean(turns_1))\n", | |
| "print(np.mean(turns_2))\n", | |
| "print(np.mean(turns_3))\n", | |
| "print(np.mean(turns_4))\n", | |
| "print('-----')\n", | |
| "print('Avg. of not player_1:')\n", | |
| "print((np.mean(turns_2) + np.mean(turns_3) + np.mean(turns_4)) / 3)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 38, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>Player</th>\n", | |
| " <th>Win Count</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>2</th>\n", | |
| " <td>player_1</td>\n", | |
| " <td>13364</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>0</th>\n", | |
| " <td>player_2</td>\n", | |
| " <td>12271</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>3</th>\n", | |
| " <td>player_3</td>\n", | |
| " <td>11987</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>1</th>\n", | |
| " <td>player_4</td>\n", | |
| " <td>11897</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Player Win Count\n", | |
| "2 player_1 13364\n", | |
| "0 player_2 12271\n", | |
| "3 player_3 11987\n", | |
| "1 player_4 11897" | |
| ] | |
| }, | |
| "execution_count": 38, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "data" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 40, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "player_1 does this % better over time than other players:\n" | |
| ] | |
| }, | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "0.10889226939565765" | |
| ] | |
| }, | |
| "execution_count": 40, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "print('player_1 does this % better over time than other players:')\n", | |
| "(13364 - np.mean([12271, 11987, 11897])) / np.mean([12271, 11987, 11897])" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 41, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "63.723434468689376\n", | |
| "16\n", | |
| "187\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# what is the avg, min, max number of turns in a game?\n", | |
| "print(np.mean(round_counts))\n", | |
| "print(np.min(round_counts))\n", | |
| "print(np.max(round_counts))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 42, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "Text(0.5, 1.0, 'Dist of Game Duration over 50k Games')" | |
| ] | |
| }, | |
| "execution_count": 42, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| }, | |
| { | |
| "data": { | |
| "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYsAAAEWCAYAAACXGLsWAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAmGElEQVR4nO3dffxUZZ3/8dcbVDQRlUBDEMFE86byBsmyzFITuxF0o6VtV2zdJc1q1WqFX7fbLpt2Z+uWmlYLbKmLpUm2lkRQW94QmIVoCIo3JAFqKqhp4Of3x3WNHIaZOQNfZr7zhffz8TiPOec6d5+5vvM9nznnOnMdRQRmZmaN9OruAMzMrPM5WZiZWSknCzMzK+VkYWZmpZwszMyslJOFmZmVcrLo4SRdIelTbdjPsZKWSForaWyr97etyvW3f3fH0SkkhaQDujsOK+dk0cEkPSjpOUlrJD0p6VZJZ0t66e8WEWdHxL82ua0TuxDO54CvRUTfiPhBnX2Ml3SHpGckrcrjH5SkLuy3yyQNyweltXlYKekmSSe1eL9zJf1DsSzX3wOt3G871ajbtcUvL0oulvR4Hr6wpZ8HSTtJ+rSkxfkz9gdJN0t629Z7R1aPk0Xne1dE7AbsB1wEXAh8qxvi2A9YVG+mpI8C/wF8EXgFsDdwNnAssFM7AmzCHhHRF3gtMAu4QdKZW7IhSTtszcB6gpL3vEdOhH2rvrxMBMaS6vw1wDuBD2xhCN8DxgBnAHsCw0mfuXds4fZsc0SEhw4dgAeBE6vKRgEvAofl6anAv+XxAcBNwJPAE8D/kb4Q/Hde5zlgLfDPdfb3j8DSvO5MYJ9cfn/V+n2q1tsdeAb4q5L38w7gN8DTwCPAZwvzhgEBvD/P+xMp2RwN/C6/p69Vbe/vgXvzsj8B9quz38q2d6gq/xiwEuiVpwM4oDC/WLfHA8tJyfqPuU73zPW9OsdwEzAkLz8FWA/8OdfZ16r3kettel7/IeCThVjOBH4JfClvexlwSoO6PRiYm+tpEXBqLj8mx9u7sOxpwO/yeC9gUv4bPw7MAPpX1dtZwMPAL5qt28L8W4GJhemzgNsL08X6eGP+27+lxnZOJH3+hpR8xirvZQ1wD3BaYd6ZwK+AS3I9PQC8IZc/AqwCJhSW75Pr/+H8ObkC2KXR/1p3HzNaOXR7AB4a/HFqJItc/jBwTh6fyoYD2ufzB3rHPLwJUKNtFbb5VuAx4Mj8T/KfxYNDo/WB0cC6egeMwnLHA6/OB6jX5H/AsXle5aBzBbAz8DbSgfYHwF7A4PzP/Oa8/FhSYjsY2IF0oL21zn5rHtCA/XP5wXm6LFmsAy7O9bML8HLgr4CXAbsB1wE/KKw/F/iHqn0WD47TgRvzusOA+4Cz8rwzgb+QEnhv4Bzg0crfs2qbO+a6+H+ks7i3kg6WB+X59wMnFZa/DpiUx88DbgeG5Pf1DeCaqnqbDuxKPlDWqds/kJLpfwEDCvOfAl5XmB4JrKmuD+Bk0gF7VJ2/4UXA3Cb+Z8YB+5A+Y39N+hIzqFCn60hfSHoD/0b6X/p6fu9vy/XWNy//VdKXpv75b/RD4PNl/2vb6tDtAXho8MepnyxuBz6Rx6ey4YD2uXzwOaDZbRXmfwv4QmG6bz5YDStbH/hb4I9VZbeSvnU9BxxXZ72vApfk8cpBZ3Bh/uPAXxemvw+cl8dvJh9Y83Qv4FlqnF1QP1nsnMuPzdNlyeIFYOcGdXg48KfC9FzqJIt8sHoeOKQw7wPkA2I+sC0tzHtZXvcVNfb7JtLZQ69C2TXkMzfSQfHbeXw30gF0vzx9L3BCYb1B+e++Q6He9m/wnvuSEsAOpEuP3wN+Upi/HnhVYXpE3qYK9TGZdGb16gb7+SZwbWG6f/58PQX8ucF6dwFjCnW6pDDv1Xn/e1d95g4HlOvplYV5rweWlf2vbauD2yx6psGkU99qXyR9w7xF0gOSJm3GNvch/cMCEBFrSf84g5tY93FgQPGadkS8ISL2yPN6AUh6naQ5klZLeop0mWlA1bZWFsafqzHdN4/vB/xHbvh/klQfajLeisqyteqyltUR8efKhKSXSfqGpIckPQ38AthDUu8mtjWAdBbwUKHsITaO/4+VkYh4No/2ZVP7AI9ExIt1tnU1cLqkPsDpwJ0RUdnvfqS2m0o93ks6wO9d2NYj9d5ERKyNiPkRsS4iVgIfAt4mqV9eZC3Qr7BKP2Bt5CNudh4wIyIW1tsP6XM0qLDfJ/Ln6yjSWQEAks6QdFfh/RzGxp+x6s8TOe5iWV9gIClBLyhs68e5HLr2v9YjOVn0MJKOJh0Eflk9LyLWRMRHI2J/4F3ABZJOqMwu2fSjpANHZT+7ki6z/KGJsG4jfUseU7Lc1aTT+n0jYnfSafyW3in1CPCBiNijMOwSEbduxjZOI13aWpynnyUdICpeUbV8dR1+FDiIdJmlH3BcLled5YseI32D369QNpTm6rvao8C+xbvkituKiHtIyeMU4G9If4eKR0htIcV63DkiinGUfXaKKstW6mARqXG74rVseqPEOGCspPMabHc2cLSkIfUWkLQfcBUpYb08J5O72bLP2GOkxHFooV52j3SDRNn/2jbJyaKHkNRP0juBa4Hv1PoWJumdkg7ItyY+TfqGuD7PXkm6Rl/P1cD7JR2ev4H+O3BHRDxYFltEPAn8C3CZpHdL6iupl6TDSde6K3YDnoiIP0saRTpwbakrgMmSDgWQtLukcc2sKGlvSR8CPgNMLnwjvwv4G0m9JY0G3lyyqd1IB5QnJfXP2yuqW+cRsZ7UmDxF0m75QHcB8J1m3kOVO0iXTP5Z0o6SjicdwK4tLHM18BFSQruuUH5FjmE/AEkDJZUl/Zfks8WD8t/75cClpEtpT+VFppMOpIMl7UNKsFOrNvMocALwEUkfrLWfiLgFmAP8IO9zJ0k7khrwK3YlJavVObb3k84sNlv+TFwFXCJpr7y9wZJOzuON/te2Td19HcxD/YHUTvAcqdHtKdI3+HPZ+M6WqWy4rn5+XucZUmPjpwrLjSE15j0JfKzO/s4mNYY+QeHOnkIsdds88jLvA+aRvqGvJh3EJgI75fnvJn3DXZO3/zVS4oMa7Qr5PRxfmP4O8MnC9N8BC9lwd9W368RV2fbaXDergP8FRlctN5L0rXcN6W6na6i6G6pq+X1I7RJrSY3THyi+B9I17vtIdzNdmsuKDdx75ve0Osf/aaruhqra30ZtKlXzDgV+nj8nG90FlOcPJd3R9qOq8l6kJLU4v+/7gX+v9zepsd/3ku7UegZYQUoOryjMF/CF/Jl6Io+r1nsi3Qr7EFXtPIVl+wCfBZbkz9hyUtvVyYVlpuT9PAZ8JdfJP9SqU1LbUVTtYznwxjy+M+lL0wP5M3Yv8JGy/7Vtdag0MpmZmdXly1BmZlbKycLMzEo5WZiZWSknCzMzK7XNdoY2YMCAGDZsWHeHYWbWoyxYsOCxiBhYXb7NJothw4Yxf/787g7DzKxHkfRQrXJfhjIzs1JOFmZmVsrJwszMSjlZmJlZKScLMzMr5WRhZmalWpYscrfFdxWGpyWdJ6m/pFmSluTXPQvrTJa0VNLiSlfAufwoSQvzvEtzt8BmZtYmLUsWEbE4Ig6PiMNJT7N6FriB9ED12RExgvRAk0kAkg4BxpO6Wh5NejZC5Yljl5O6uh6Rh9GtitvMzDbVrstQJwD3R3qU4xhgWi6fBozN42NIz9h9PiKWkR5ZOErSIKBfRNwWqT/16YV1zMysDdr1C+7xpAfJQHo4+gqAiFhReQoV6VGhtxfWWZ7L/pLHq8s3IWki6QyEoUOHbrXg2+2SWfd1af3zTzpwK0ViZpa0/MxC0k7AqWz8KMeai9YoiwblmxZGXBkRIyNi5MCBm3RtYmZmW6gdl6FOAe6MiJV5emW+tER+XZXLlwP7FtYbQno27/I8Xl1uZmZt0o5k8V42XIICmAlMyOMTgBsL5eMl9ZE0nNSQPS9fsloj6Zh8F9QZhXXMzKwNWtpmIellwEmkB9lXXATMkHQW8DAwDiAiFkmaQXrY/Drg3IhYn9c5B5gK7EJ6QPvNrYzbzMw21tJkERHPAi+vKnucdHdUreWnAFNqlM8HDmtFjGZmVs6/4DYzs1JOFmZmVsrJwszMSjlZmJlZKScLMzMr5WRhZmal2tU3lLWR+5Yys63NZxZmZlbKycLMzEo5WZiZWSknCzMzK+VkYWZmpZwszMyslJOFmZmVcrIwM7NSThZmZlbKycLMzEq5u48W6Gp3G2ZmncZnFmZmVsrJwszMSjlZmJlZqZYmC0l7SPqepN9LulfS6yX1lzRL0pL8umdh+cmSlkpaLOnkQvlRkhbmeZdKUivjNjOzjbX6zOI/gB9HxKuA1wL3ApOA2RExApidp5F0CDAeOBQYDVwmqXfezuXARGBEHka3OG4zMytoWbKQ1A84DvgWQES8EBFPAmOAaXmxacDYPD4GuDYino+IZcBSYJSkQUC/iLgtIgKYXljHzMzaoJVnFvsDq4H/kvQbSd+UtCuwd0SsAMive+XlBwOPFNZfnssG5/Hq8k1ImihpvqT5q1ev3rrvxsxsO9bKZLEDcCRweUQcATxDvuRUR612iGhQvmlhxJURMTIiRg4cOHBz4zUzszpamSyWA8sj4o48/T1S8liZLy2RX1cVlt+3sP4Q4NFcPqRGuZmZtUnLkkVE/BF4RNJBuegE4B5gJjAhl00AbszjM4HxkvpIGk5qyJ6XL1WtkXRMvgvqjMI6ZmbWBq3u7uPDwHcl7QQ8ALyflKBmSDoLeBgYBxARiyTNICWUdcC5EbE+b+ccYCqwC3BzHszMrE1amiwi4i5gZI1ZJ9RZfgowpUb5fOCwrRqcmZk1zb/gNjOzUk4WZmZWysnCzMxK+XkWtomuPo/j/JMO3EqRmFmn8JmFmZmVcrIwM7NSThZmZlbKycLMzEo5WZiZWSknCzMzK+VkYWZmpZwszMyslJOFmZmVcrIwM7NSThZmZlbKycLMzEo5WZiZWSknCzMzK+VkYWZmpZwszMysVEuThaQHJS2UdJek+bmsv6RZkpbk1z0Ly0+WtFTSYkknF8qPyttZKulSSWpl3GZmtrF2nFm8JSIOj4iReXoSMDsiRgCz8zSSDgHGA4cCo4HLJPXO61wOTARG5GF0G+I2M7OsOy5DjQGm5fFpwNhC+bUR8XxELAOWAqMkDQL6RcRtERHA9MI6ZmbWBq1OFgHcImmBpIm5bO+IWAGQX/fK5YOBRwrrLs9lg/N4dfkmJE2UNF/S/NWrV2/Ft2Fmtn0rTRaSxknaLY9/UtL1ko5scvvHRsSRwCnAuZKOa7SrGmXRoHzTwogrI2JkRIwcOHBgkyGamVmZZs4sPhURayS9ETiZdOno8mY2HhGP5tdVwA3AKGBlvrREfl2VF18O7FtYfQjwaC4fUqPczMzapJlksT6/vgO4PCJuBHYqW0nSroUzkl2BtwF3AzOBCXmxCcCNeXwmMF5SH0nDSQ3Z8/KlqjWSjsl3QZ1RWMfMzNpghyaW+YOkbwAnAhdL6kNzSWZv4IZ8l+sOwNUR8WNJvwZmSDoLeBgYBxARiyTNAO4B1gHnRkQlUZ0DTAV2AW7Og5mZtUkzyeI9pFtVvxQRT+ZLRx8vWykiHgBeW6P8ceCEOutMAabUKJ8PHNZErGZm1gKlZwgR8SypXeGNuWgdsKSVQZmZWWdp5m6ozwAXApNz0Y7Ad1oZlJmZdZZm2h5OA04FnoGX7nDarZVBmZlZZ2mmzeKFiAhJAS/d2WRW1yWz7uvS+uefdOBWisTMtpZmzixm5Luh9pD0j8BPgataG5aZmXWS0jOLiPiSpJOAp4GDgE9HxKyWR2ZmZh2jmctQRMQsSXdUlpfUPyKeaGlkZmbWMUqThaQPAJ8DngNeJPXVFMD+rQ3NzMw6RTNnFh8DDo2Ix1odjJmZdaZmGrjvB55tdSBmZta5mjmzmAzcmtssnq8URsRHWhaVmZl1lGaSxTeAnwELSW0WZma2nWkmWayLiAtaHomZmXWsZtos5uTHlQ6S1L8ytDwyMzPrGM2cWfxNfp1cKPOts2Zm25FmfsE9vB2BmJlZ52rqF9ySDgMOAXaulEXE9FYFZWZmnaWZX3B/BjielCz+FzgF+CXgZGFmtp1opoH73aTHoP4xIt5PelRqn5ZGZWZmHaWZZPFcRLwIrJPUj/SIVTdum5ltR5pps5gvaQ/SMywWAGuBea0MyszMOkvpmUVEfDAinoyIK4CTgAn5clRTJPWW9BtJN+Xp/pJmSVqSX/csLDtZ0lJJiyWdXCg/StLCPO9SSdq8t2lmZl1RN1nkg3zfwvQxwFDSE/M25xnc/wTcW5ieBMyOiBHA7DyNpEOA8cChwGjgMkm98zqXAxOBEXkYvRn7NzOzLmp0ZnEx8MHC9DXAx4FPAZ9sZuOShgDvAL5ZKB4DTMvj04CxhfJrI+L5iFgGLAVGSRoE9IuI2yIiSHdhjcXMzNqmUZvFCcDRheknI+Jd+RLQ/zW5/a8C/wwUz0T2jogVABGxQtJeuXwwcHthueW57C95vLp8E5Imks5AGDp0aJMhmplZmUZnFr0iYl1h+kKA/O2+b+1VNpD0TmBVRCxoMpZa7RDRoHzTwogrI2JkRIwcOHBgk7s1M7Myjc4sdpK0W0SsAYiIWwAk7U7hl9wNHAucKuntefl+kr4DrJQ0KJ9VDCLdigvpjGHfwvpDgEdz+ZAa5WZm1iaNziyuAv5H0kvXcyTtR2q7uKpswxExOSKGRMQwUsP1zyLib4GZwIS82ATgxjw+ExgvqY+k4aSG7Hn5ktUaScfkS2BnFNYxM7M2qHtmERFfkfQs8EtJu5Iu/TwDXBQRl3dhnxcBMySdBTwMjMv7WyRpBnAPsA44NyLW53XOAaYCuwA358G2UZfMuq9L659/0oFbKRIzq2j4o7z824or8i20qlyS2lwRMReYm8cfJzWe11puCjClRvl84LAt2beZmXVdU73ORsTaVgdiZmadq5m+oczMbDvX6Bfc4/KrH35kZrada3RmUXmM6vfbEYiZmXWuRm0Wj0uaAwyXNLN6ZkSc2rqwzMyskzRKFu8AjgT+G/hye8IxM7NO1Oh3Fi8At0t6Q0Sszj3Nhu+MMjPb/jRzN9Tekn4D3A3cI2mBJP/mwcxsO9JMsrgSuCAi9ouIocBHc5mZmW0nmkkWu0bEnMpE/jX2ri2LyMzMOk4zv+B+QNKnSA3dAH8LLGtdSGZm1mmaObP4e2AgcH0eBgBNP4PbzMx6vtIzi4j4E/CRNsRiZmYdyn1DmZlZKScLMzMrVZosJB3bTJmZmW27mjmz+M8my8zMbBtVt4Fb0uuBNwADJV1QmNUP6N3qwMzMrHM0uhtqJ6BvXma3QvnTwLtbGZSZmXWWRh0J/hz4uaSpEfFQG2MyM7MO00ybRR9JV0q6RdLPKkPZSpJ2ljRP0m8lLZL0L7m8v6RZkpbk1z0L60yWtFTSYkknF8qPkrQwz7tUkrbo3ZqZ2RZppruP64ArgG8C6zdj288Db42ItZJ2BH4p6WbgdGB2RFwkaRIwCbhQ0iHAeOBQYB/gp5IOjIj1wOXAROB24H+B0cDNmxGLmZl1QTPJYl1EXL65G46IACrPvtgxDwGMAY7P5dOAucCFufzaiHgeWCZpKTBK0oNAv4i4DUDSdGAsThZmZm3TTLL4oaQPAjeQzhYAiIgnylaU1BtYABwAfD0i7pC0d0SsyNtYIWmvvPhg0plDxfJc9pc8Xl1ea38TSWcgDB06tIm3ZtuiS2bd16X1zz/pwK0Uidm2o5lkMSG/frxQFsD+ZSvmS0iHS9oDuKHkoUm12iGiQXmt/V1JftbGyJEjay5jZmabr5mOBId3dScR8aSkuaS2hpWSBuWzikHAqrzYcmDfwmpDgEdz+ZAa5WZm1ialyULSGbXKI2J6yXoDgb/kRLELcCJwMTCTdLZyUX69Ma8yE7ha0ldIDdwjgHkRsV7SGknHAHcAZ+BfkJuZtVUzl6GOLozvDJwA3Ak0TBbAIGBabrfoBcyIiJsk3QbMkHQW8DAwDiAiFkmaAdwDrAPOzZexAM4BpgK7kBq23bhtZtZGzVyG+nBxWtLubHhqXqP1fgccUaP8cVLCqbXOFGBKjfL5QKP2DjMza6Et6aL8WdIlIjMz204002bxQzbcfdQbOBiY0cqgzMysszTTZvGlwvg64KGIWF5v4W1BV+/TNzPb1pRehsodCv6e1PPsnsALrQ7KzMw6SzNPynsPMI9019J7gDskuYtyM7PtSDOXoT4BHB0Rq+Cl30/8FPheKwMzM7PO0czdUL0qiSJ7vMn1zMxsG9HMmcWPJf0EuCZP/zX+UZyZ2XalmR/lfVzS6cAbSZ36XRkRN7Q8MjMz6xh1k4WkA4C9I+JXEXE9cH0uP07SKyPi/nYFaWZm3atR28NXgTU1yp/N88zMbDvRKFkMy/07bST30zSsZRGZmVnHaZQsdm4wb5etHYiZmXWuRg3cv5b0jxFxVbEwdy2+oLVhmXUfP5bVbFONksV5pEehvo8NyWEksBNwWovjMjOzDlI3WUTESuANkt7ChmdJ/CgiftaWyMzMrGM08zuLOcCcNsRiZmYdyt12mJlZKScLMzMr5WRhZmalnCzMzKxUy5KFpH0lzZF0r6RFkv4pl/eXNEvSkvy6Z2GdyZKWSlos6eRC+VGSFuZ5l0pSq+I2M7NNtfLMYh3w0Yg4GDgGOFfSIcAkYHZEjABm52nyvPHAocBo4DJJvfO2LgcmAiPyMLqFcZuZWZWWJYuIWBERd+bxNcC9wGBgDDAtLzYNGJvHxwDXRsTzEbEMWAqMkjQI6BcRt0VEANML65iZWRu0pc1C0jDgCOAOUrfnKyAlFGCvvNhg4JHCastz2eA8Xl1eaz8TJc2XNH/16tVb9T2YmW3PWp4sJPUFvg+cFxFPN1q0Rlk0KN+0MOLKiBgZESMHDhy4+cGamVlNLU0WknYkJYrv5gcoAazMl5bIr5Xney8H9i2sPgR4NJcPqVFuZmZt0sq7oQR8C7g3Ir5SmDUTmJDHJwA3FsrHS+ojaTipIXtevlS1RtIxeZtnFNYxM7M2KO0bqguOBf4OWCjprlz2/4CLgBm5q/OHgXEAEbFI0gzgHtKdVOdGxPq83jnAVNJzNG7Og5mZtUnLkkVE/JLa7Q0AJ9RZZwowpUb5fDb0fGtmZm3WyjMLs+2SH55k2yJ392FmZqWcLMzMrJSThZmZlXKyMDOzUk4WZmZWysnCzMxKOVmYmVkpJwszMyvlZGFmZqWcLMzMrJS7+zDrMO4uxDqRzyzMzKyUk4WZmZVysjAzs1JOFmZmVsrJwszMSjlZmJlZKScLMzMr5WRhZmalWpYsJH1b0ipJdxfK+kuaJWlJft2zMG+ypKWSFks6uVB+lKSFed6lktSqmM3MrLZWnllMBUZXlU0CZkfECGB2nkbSIcB44NC8zmWSeud1LgcmAiPyUL1NMzNrsZZ19xERv5A0rKp4DHB8Hp8GzAUuzOXXRsTzwDJJS4FRkh4E+kXEbQCSpgNjgZtbFbdZT+fuQqwV2t1msXdErADIr3vl8sHAI4XllueywXm8urwmSRMlzZc0f/Xq1Vs1cDOz7VmnNHDXaoeIBuU1RcSVETEyIkYOHDhwqwVnZra9a3eyWClpEEB+XZXLlwP7FpYbAjyay4fUKDczszZqd7KYCUzI4xOAGwvl4yX1kTSc1JA9L1+qWiPpmHwX1BmFdczMrE1a1sAt6RpSY/YAScuBzwAXATMknQU8DIwDiIhFkmYA9wDrgHMjYn3e1DmkO6t2ITVsu3HbrIXcQG61tPJuqPfWmXVCneWnAFNqlM8HDtuKoZmZ2WbqlAZuMzPrYE4WZmZWysnCzMxKOVmYmVkpJwszMyvVsruhzGz75Ftvu6ZT689nFmZmVsrJwszMSjlZmJlZKScLMzMr5WRhZmalfDeUmXWUTr0baHvnZGFm2xQnm9bwZSgzMyvlZGFmZqWcLMzMrJTbLMzMCtzmUZuThZnZVtTVZNOpfBnKzMxKOVmYmVkpJwszMyvVY5KFpNGSFktaKmlSd8djZrY96RHJQlJv4OvAKcAhwHslHdK9UZmZbT96RLIARgFLI+KBiHgBuBYY080xmZltN3rKrbODgUcK08uB11UvJGkiMDFPrpW0uA2x1TIAeKyb9r0lelq80PNi7mnxQs+LuafFCy2I+YKub2K/WoU9JVmoRllsUhBxJXBl68NpTNL8iBjZ3XE0q6fFCz0v5p4WL/S8mHtavNCzYu4pl6GWA/sWpocAj3ZTLGZm252ekix+DYyQNFzSTsB4YGY3x2Rmtt3oEZehImKdpA8BPwF6A9+OiEXdHFYj3X4pbDP1tHih58Xc0+KFnhdzT4sXelDMitjk0r+ZmdlGesplKDMz60ZOFmZmVsrJogsk7StpjqR7JS2S9E+5/LOS/iDprjy8vbtjLZL0oKSFObb5uay/pFmSluTXPbs7TgBJBxXq8S5JT0s6r9PqWNK3Ja2SdHehrG6dSpqcu65ZLOnkDon3i5J+L+l3km6QtEcuHybpuUJdX9HueBvEXPdz0KF1/D+FWB+UdFcu74g6bigiPGzhAAwCjszjuwH3kboj+Szwse6Or0HcDwIDqsq+AEzK45OAi7s7zhpx9wb+SPrRUEfVMXAccCRwd1md5s/Ib4E+wHDgfqB3B8T7NmCHPH5xId5hxeU6rI5rfg46tY6r5n8Z+HQn1XGjwWcWXRARKyLizjy+BriX9GvznmgMMC2PTwPGdl8odZ0A3B8RD3V3INUi4hfAE1XF9ep0DHBtRDwfEcuApaQubdqmVrwRcUtErMuTt5N+z9Qx6tRxPR1ZxxWSBLwHuKadMXWFk8VWImkYcARwRy76UD6d/3anXNIpCOAWSQtyFykAe0fECkhJENir26Krbzwb/3N1ch1D/Tqt1X1Np33J+Hvg5sL0cEm/kfRzSW/qrqDqqPU56PQ6fhOwMiKWFMo6uY6dLLYGSX2B7wPnRcTTwOXAK4HDgRWk081OcmxEHEnqxfdcScd1d0Bl8o8xTwWuy0WdXseNNNV9TXeR9AlgHfDdXLQCGBoRR5C6HrpaUr/uiq9Kvc9BR9cx8F42/uLTyXUMOFl0maQdSYniuxFxPUBErIyI9RHxInAVbT79LRMRj+bXVcANpPhWShoEkF9XdV+ENZ0C3BkRK6Hz6zirV6cd232NpAnAO4H3Rb6Yni/lPJ7HF5Cu/x/YfVFu0OBz0Ml1vANwOvA/lbJOruMKJ4suyNcdvwXcGxFfKZQPKix2GnB39brdRdKuknarjJMaNe8mdZ8yIS82AbixeyKsa6NvYp1cxwX16nQmMF5SH0nDgRHAvG6IbyOSRgMXAqdGxLOF8oFKz5RB0v6keB/onig31uBz0JF1nJ0I/D4illcKOrmOX9LdLew9eQDeSDq1/R1wVx7eDvw3sDCXzwQGdXeshZj3J90l8ltgEfCJXP5yYDawJL/27+5YCzG/DHgc2L1Q1lF1TEpkK4C/kL7VntWoToFPkL49LgZO6ZB4l5Ku81c+y1fkZf8qf1Z+C9wJvKuD6rju56AT6ziXTwXOrlq2I+q40eDuPszMrJQvQ5mZWSknCzMzK+VkYWZmpZwszMyslJOFmZmVcrKwbiEpJH25MP0xSZ/dStueKundW2NbJfsZp9Tj8JxC2asLPYc+IWlZHv9pG+I5W9IZm7nOCEk3Sbo/d/8ypyf8ot/ar0c8VtW2Sc8Dp0v6fEQ81t3BVEjqHRHrm1z8LOCDEfFSsoiIhaSuJ5A0FbgpIr7X5L53iA0d+W22iNisbq0l7Qz8iNRr68xcdhgwEvjFlsZh2yafWVh3WUd6/vD51TOqzwwkrc2vx+dO1mZIuk/SRZLeJ2me0vM5XlnYzImS/i8v9868fm+lZzb8Onc894HCdudIupr0A6/qeN6bt3+3pItz2adJP8q8QtIXy96spLmSRubxAZIezONnSrpO0g9JnTueKel6ST9Weg7GFwqxT80xLJRUq94+K+ljhf1dnOvmvjod070PuK2SKAAi4u6ImJq3MUrSrblzu1slHVSI+QeSfpjPnD4k6YK83O2S+uflXpnfx4L8t3hVWT1Z5/KZhXWnrwO/qxwQm/Ra4GBS188PAN+MiFFKD576MHBeXm4Y8GZSJ3NzJB0AnAE8FRFHS+oD/ErSLXn5UcBhkbqzfomkfUjPdjgK+BPpgD42Ij4n6a2kb+XzN/eNV3k98JqIeELSmaQzkyNIZ1+LJf0nqcfawRFxWI5rjya2u0Oum7cDnyF1M1F0KOnXwvX8HjguItZJOhH4d9IvjQEOyzHuTPrl94URcYSkS0j1/FXSl4GzI2KJpNcBlwFvbSJu60BOFtZtIuJpSdOBjwDPNbnaryN3+y3pfqBysF8IvKWw3IxIncstkfQA8CpSP1ivKZy17E7qg+cFYF51osiOBuZGxOq8z++SHmrzgybjbcasiCg+92B2RDyV93cP6WFPi4D9c+L4ERvedyPX59cFpOTZkKQbSPVxX0ScTqqfaZJGkLq12bGw+JxIz3BZI+kp4Ie5fCGpjvsCbwCuk17qALZPEzFbh/JlKOtuXyVd+9+1ULaO/NlUOtLsVJj3fGH8xcL0i2z85ae6H5sgdVv94Yg4PA/DI6Jy0H2mTny1urreEi+9J9K38aLqfRff43rSGcKfSGdVc4FzgW82sc/KdtZT+4vhItKT3ACIiNOAM4H+uehfSUnhMOBdVXGX/R16AU8W6vrwiDi4iZitQzlZWLfK36hnkBJGxYOkyz6Qnni2I5tvnKReuR1jf1Jncj8BzlHqVh5JByr1vNvIHcCbcztDb1Lvtz/fgngeZMN72uw7tSQNAHpFxPeBT1E4yHfB1cCxkk4tlL2sML478Ic8fubmbDjSc12WSRoHKelLem0XYrVu5mRhneDLwIDC9FWkA/Q84HXU/9bfyGLSQf1m0nXzP5O+jd8D3CnpbuAblFyKzZe8JgNzyD2CRsSWdN/+JVKiupWN32uzBgNzJd1F6rV08hZsYyMR8Rzp2RVnS3pA0m3AJ4F/y4t8Afi8pF+Rnn++ud4HnCWp0sPxmK7GbN3Hvc6amVkpn1mYmVkpJwszMyvlZGFmZqWcLMzMrJSThZmZlXKyMDOzUk4WZmZW6v8DAGv3G9QYC/gAAAAASUVORK5CYII=\n", | |
| "text/plain": [ | |
| "<Figure size 432x288 with 1 Axes>" | |
| ] | |
| }, | |
| "metadata": { | |
| "needs_background": "light" | |
| }, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "# create histogram for number of turns in a game\n", | |
| "bins = np.linspace(math.ceil(min(round_counts)), \n", | |
| " math.floor(max(round_counts)),\n", | |
| " 20) # fixed number of bins\n", | |
| "\n", | |
| "plt.hist(round_counts, bins=bins, alpha=0.5)\n", | |
| "plt.xlabel(\"Number of Turns in Game\")\n", | |
| "plt.ylabel(\"Count of Games\")\n", | |
| "plt.title(\"Dist of Game Duration over 50k Games\")" | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3", | |
| "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.5" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 4 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment