#Import the game!
import sys
sys.path.append('game_engines')
from q_tic_tac_toe import Board

#inputs are (X,Y,print_info).
#X,Y are the dimensions of the board. print_info boolean controls if to print instructions at game launch.
#Since it is our first time playing, lets set it True and see the instructions!
B = Board(3,3,True)

B.run()

"""
Explanation: <img src="../../images/qiskit-heading.gif" alt="Note: In order for images to show up in this jupyter notebook you need to select File => Trusted Notebook" width="500 px" align="left">
Quantum Tic-Tac-Toe
The latest version of this notebook is available on https://github.com/qiskit/qiskit-tutorial.

Contributors
Maor Ben-Shahar

An example run of quantum Tic-Tac-Toe is provided below, with explanations of the game workings following after. Despite the ability to superimpose moves, a winning strategy still exists for both players (meaning the game will be a draw if both implement it). See if you can work it out.
End of explanation
"""


B = Board(3,3)
B.run()

"""
Explanation: When playing the game, the two players are asked in turn if to make a classical (1 cell) or quantum move (1 or 2 cells at most, for now). When making any move there are several scenarios that can happen, they are explained below. The terminology used:

Each turn a "move" is made
Each move consists of one or two "cells", the location(s) where the move is made. It is a superposition of classical moves.

Quantum moves are restricted to two cells only due to them requiring an increasing number of qubits, which is slow to simulate.
One move on an empty cell
This is the simplest move, it is a "classical" move. The game registers this move as a set of coordinates, and the player who made the move. No qubits are used here. 
It is registered as such:
Play in one or two cells?1
x index: 0
y index: 0
First the player is asked how many moves (we chose 1, classical). Then it asks for the index of the move.
And the board registers it as
[['O1','',''],
 ['','',''],
 ['','','']]
This move is always present at the end of the game.
Two-cell moves in empty cells
This is a quantum move, the game stores a move that is in a superposition of being played at two cells. Ordered coordinates for the two cells to be occupied need to be provided. A row in the board with a superposition move would look like so
[X1,X1,''] 
Two qubits were used in order to register this move. They are in a state $|10>+|01>$, if the first qubit is measured to be 1 then the board becomes [X1,'',''] and vice versa. Why can we not use just one qubit to record this? We can, and the qubit would have to be put into a state $|0>+|1>$ but I did not implement this yet since this is method will be consistant with later types of quantum moves.
Let us see this in action:
End of explanation
"""


B = Board(3,3)
B.add_move([[0,0],[0,1]],0) #Directly adding moves, ([indx1,indx2],player) 0=X, 1=O.
B.add_move([[0,0]],1)
B.compute_winner()

"""
Explanation: The game outcome is almost 50% in each cell, as we would expect. There is a redundant bit at the end of the bit code (to be removed soon!). And note that the bit strings are the inversed order to what we write here, this is because the quantum register in qiskit has positions $|q_n,...,q_0>$.
One-cell move plyed in a maybe-occupied cell
It is possible that after the game is in state [X1,X1,''] one would definitely want to make a move at position (0,0). This could be when the game is completely full perhaps, since it is not a very good strategy. Such a move can be erased from the game history! Let us see how it is recorded. The first row of the board is now 
[X1 O2,X1,'']
and the state of the game qubits is
$$ |100>+|011> $$
with the first qubit recording sucess of the first move at cell (0,0), the second qubit is the success of the first move in cell (0,1) and the third qubit is the move by player O, which is anti correlated with the move by X at cell (0,0).
Notice that this move can be completely erased!
End of explanation
"""


B = Board(3,3)
#Instead of running the game, for the purpose of demonstrating, we can just create the appropriate state manually.
#Directly adding moves, ([[y1,x1],[x2,y2]],player) with player=0->X, 1->O.
B.add_move([[0,0],[0,1]],0)
B.add_move([[0,0],[0,2]],1)
B.compute_winner()

"""
Explanation: Once again note that the move could be erased completely, and in fact this happens 50% of the time. Notice how the bit string output from QISKIT is translated into a board state.
Two-cell moves in maybe-occupied cells
Instead of the above, player O might like to choose a better strategy. Perhaps O is interested in a quantum move on cells (0,0) and (0,2). In such a case the game records the two moves in the order they are entered.

In order (0,0) then (0,2): The state of the game is first made into $ |100>+|011> $ as above, with the third qubit recording the sucess of player O getting position (0,0). Then the (0,2) position is registered, anti-correlated with suceeding in position (0,0): $|1001>+|0110>$. Now, unlike before, player O suceeds in registering a move regardless of the outcome. 
In order (0,2) then (0,0): Now playing at (0,2) is not dependent on anything, and so the game state is $(|10>+|01>)\otimes (|1>+|0>) = |101>+|100>+|011>+|010>$. And when the move in position (0,0) is added too, it is anti correlated with BOTH the move in (0,2) AND the pre-existing move in (0,0). So qubit state becomes $|1010>+|1000>+|0110>+|0101>$. Notice how now the move could be erased, so order does matter!
End of explanation
"""


