-
-
Save ayazskhan/3bd012302f881dacb5962342df3c3401 to your computer and use it in GitHub Desktop.
Quantum Game Demo
This file contains 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": [ | |
"# Making a Quantum Game" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Import standard Qiskit stuff" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"%matplotlib inline\n", | |
"# Importing standard Qiskit libraries and configuring account\n", | |
"from qiskit import QuantumCircuit, execute, Aer, IBMQ\n", | |
"from qiskit.compiler import transpile, assemble\n", | |
"from qiskit.tools.jupyter import *\n", | |
"from qiskit.visualization import *\n", | |
"# Loading your IBM Q account(s)\n", | |
"provider = IBMQ.load_account()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"And numpy." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Here's a simple element that could be part of a game: damage for an enemy that takes 3 hits to defeat." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"damage = 0\n", | |
"\n", | |
"def attack(damage):\n", | |
" \n", | |
" damage = min( damage + 1/3 , 1)\n", | |
" \n", | |
" return damage" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"We could instead use a quantum circuit to store the damage value, and a quantum gate to implement the attack." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"damage_qc = QuantumCircuit(1,1)\n", | |
"\n", | |
"def attack(damage_qc):\n", | |
" \n", | |
" damage_qc.rx(np.pi/3,0)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"We need to run the circuit to get information out." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"meas = QuantumCircuit(1,1)\n", | |
"meas.measure(0,0)\n", | |
"\n", | |
"qc = damage_qc+meas\n", | |
" \n", | |
"counts = execute(qc, Aer.get_backend('qasm_simulator'), shots=1000).result().get_counts()\n", | |
"\n", | |
"print(counts)\n", | |
"qc.draw()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Let's put this in a function." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_damage(damage_qc):\n", | |
" \n", | |
" meas = QuantumCircuit(1,1)\n", | |
" meas.measure(0,0)\n", | |
"\n", | |
" qc = damage_qc+meas\n", | |
"\n", | |
" counts = execute(qc, Aer.get_backend('qasm_simulator'), shots=1000).result().get_counts()\n", | |
" \n", | |
" damage = 0\n", | |
" if '1' in counts:\n", | |
" damage = counts['1']/1000\n", | |
" \n", | |
" return damage" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"damage = get_damage(damage_qc)\n", | |
"print(damage)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This used just a single qubit. Let's do some fancier things, but still with a single qubit. We'll use our knowledge of the [Bloch sphere](https://javafxpert.github.io/grok-bloch/).\n", | |
"\n", | |
"We'll use [this](https://github.com/quantumjim/jupyter-widget-game-engine/blob/master/jupyter_widget_game.ipynb) very simple game engine that runs in Jupyter notebooks. You can download with the following." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"!git clone https://github.com/quantumjim/jupyter-widget-game-engine/\n", | |
"!mv jupyter-widget-game-engine/jupyter_widget_engine.py jupyter_widget_engine.py\n", | |
"!mv jupyter-widget-game-engine/jupyter_widget_game.ipynb jupyter_widget_game.ipynb\n", | |
"!rm -r jupyter-widget-game-engine" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Then import the game engine." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from jupyter_widget_engine import jupyter_widget_engine" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This gives us an LxL screen of pixels and a controller." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"scrolled": false | |
}, | |
"outputs": [], | |
"source": [ | |
"L = 8\n", | |
"\n", | |
"def start(engine):\n", | |
" pass\n", | |
"\n", | |
"def next_frame(engine):\n", | |
" pass \n", | |
" \n", | |
"engine = jupyter_widget_engine(start,next_frame,L=L)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Let's make a simple walking simulator, where you just walk around and explore a 2D map." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_terrain(x,y):\n", | |
" return 'grass'" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def start(engine):\n", | |
" \n", | |
" engine.get_terrain = get_terrain\n", | |
" \n", | |
" engine.next_frame(engine)\n", | |
"\n", | |
"def next_frame(engine):\n", | |
"\n", | |
" for x in range(L):\n", | |
" for y in range(L):\n", | |
" if engine.get_terrain(x,y)=='grass':\n", | |
" engine.screen[x,y].button_style = 'success'\n", | |
" \n", | |
"engine = jupyter_widget_engine(start,next_frame,L=L)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Since grass is a bit boring, we'll use a single qubit to generate the map using the method explained [here](https://github.com/qiskit-community/MicroQiskit/blob/master/versions/MicroPython/tutorials/Terrain-Generator.ipynb)." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_terrain(x,y):\n", | |
"\n", | |
" qc = QuantumCircuit(1,1) # make a circuit\n", | |
" \n", | |
" # perform rotations, whose angles depend on x and y\n", | |
" qc.rx( (np.pi/16)*(x+y) ,0)\n", | |
" # calculate probability for outcome 1\n", | |
" qc.measure(0,0)\n", | |
" counts = execute(qc, Aer.get_backend('qasm_simulator'), shots=1000).result().get_counts()\n", | |
" if '1' in counts:\n", | |
" p = counts['1']/1000\n", | |
" else:\n", | |
" p = 0\n", | |
" \n", | |
" # return terrain depending on this probability\n", | |
" # the chosen values here are fairly arbitrarily\n", | |
" if p<0.3:\n", | |
" terrain = 'sea'\n", | |
" elif p<0.7:\n", | |
" terrain = 'sand'\n", | |
" else:\n", | |
" terrain = 'grass'\n", | |
" \n", | |
" return terrain" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This produces either grass, sand or sea. The game engine needs to be updated accordingly." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def start(engine):\n", | |
" \n", | |
" engine.get_terrain = get_terrain\n", | |
" \n", | |
" engine.next_frame(engine)\n", | |
"\n", | |
"def next_frame(engine):\n", | |
"\n", | |
" for x in range(L):\n", | |
" for y in range(L):\n", | |
" terrain = engine.get_terrain(x,y)\n", | |
" if terrain=='grass':\n", | |
" engine.screen[x,y].button_style = 'success'\n", | |
" elif terrain=='sea':\n", | |
" engine.screen[x,y].button_style = 'info'\n", | |
" else:\n", | |
" engine.screen[x,y].button_style = 'warning'\n", | |
" \n", | |
"engine = jupyter_widget_engine(start,next_frame,L=L)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"A nice beach, though very straight. By experimenting with different single qubit circuits, we can come up with better terrain.\n", | |
"\n", | |
"But let's start on the non-quantum part: walking around!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def start(engine):\n", | |
" \n", | |
" engine.get_terrain = get_terrain\n", | |
" \n", | |
" engine.p_x = 4\n", | |
" engine.p_y = 4\n", | |
" \n", | |
" engine.next_frame(engine)\n", | |
"\n", | |
"def next_frame(engine):\n", | |
" \n", | |
" if engine.controller['up'].value:\n", | |
" engine.p_y -= 1\n", | |
" if engine.controller['down'].value:\n", | |
" engine.p_y += 1\n", | |
" if engine.controller['left'].value:\n", | |
" engine.p_x -= 1\n", | |
" if engine.controller['right'].value:\n", | |
" engine.p_x += 1\n", | |
" \n", | |
" s_x = np.floor(engine.p_x/L)\n", | |
" s_y = np.floor(engine.p_y/L)\n", | |
"\n", | |
" for x in range(L):\n", | |
" for y in range(L):\n", | |
" terrain = engine.get_terrain(L*s_x+x,L*s_y+y)\n", | |
" if terrain=='grass':\n", | |
" engine.screen[x,y].button_style = 'success'\n", | |
" elif terrain=='sea':\n", | |
" engine.screen[x,y].button_style = 'info'\n", | |
" else:\n", | |
" engine.screen[x,y].button_style = 'warning'\n", | |
" \n", | |
" engine.screen[engine.p_x%L,engine.p_y%L].button_style = 'danger'\n", | |
" \n", | |
"engine = jupyter_widget_engine(start,next_frame,L=L)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Improvements that could be made:\n", | |
"* Improve terrain generation.\n", | |
"* Only calculate terrain when screen changes.\n", | |
"* Make player interact with map (no walking on water).\n", | |
"* Make an actual game!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"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.7.3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment