private double AlphaBeta(Board b, int depth, double alpha, double beta, int colour, ref Move bestMoveYet)
        {
            if (depth == 0)
                return b.ScoreBoard();
            else
            {
                if (colour == 1)
                {
                    for (int i = 0; i < b.AllMovesCount; i++)
                    {
                        Move move = b.AllMoves[i];
                        double result = AlphaBeta(b.GetBoardAfterMove(move.From, move.To), depth - 1, alpha, beta, -colour, ref bestMoveYet);
                        nodesVisited++;

                        if (result > alpha)
                        {
                            alpha = result;
                            if (depth == MaxAlphaBetaDepth) bestMoveYet = move;
                        }
                        if (beta <= alpha)
                        {
                            betaSkips++;
                            goto skip1;
                        }
                    }
                skip1:
                    return alpha;
                }
                else if (colour == -1)
                {
                    for (int i = 0; i < b.AllMovesCount; i++)
                    {
                        Move move = b.AllMoves[i];
                        double result = AlphaBeta(b.GetBoardAfterMove(move.From, move.To), depth - 1, alpha, beta, -colour, ref bestMoveYet);
                        nodesVisited++;

                        if (result < beta)
                        {
                            beta = result;
                            if (depth == MaxAlphaBetaDepth) bestMoveYet = move;
                            //bestMoveYet = move;
                        }
                        if (beta <= alpha)
                        {
                            betaSkips++;
                            goto skip2;
                        }
                    }
                skip2:
                    return beta;
                }
                else throw new ApplicationException();
            }

            throw new ApplicationException();
        }
        private double Negamax(Board b, int depth, double alpha, double beta, int colour)
        {
            Tuple<int, double> tuple = m_Zasher.GetDepthScoreTuple(b);
            // If the same or better calculation of this state has already been made, use it.
            if (tuple != null && tuple.Item1 >= depth && depth < MaxNegamaxDepth)
            {
                if (depth > 0) hashUsed++;
                if (depth >= 0) hashUsed++;
                return colour * tuple.Item2;
            }

            if (depth == 0)
            {
                double score = b.ScoreBoard();
                m_Zasher.SetDepthScoreTuple(b, new Tuple<int, double>(0, score));
                hashNotUsed++;
                return colour * score;
            }
            else
            {
                for (int i = 0; i < b.AllMovesCount; i++)
                {
                    Move move = b.AllMoves[i];
                    Board boardAfterMove = new Board(b);
                    bool moveOk = boardAfterMove.MakeMove(move.From, move.To);

                    if (moveOk)
                    {
                        double score = -Negamax(boardAfterMove, depth - 1, -beta, -alpha, -colour);

                        // Cache this score
                        m_Zasher.AddIfBetter(boardAfterMove, new Tuple<int, double>(depth - 1, colour * score));

                        nodesVisited++;
                        if (score >= beta)
                            return score;
                        if (score > alpha)
                        {
                            alpha = score;
                        }

                        if (depth == MaxNegamaxDepth)
                        {
                            m_RankedMoves.Add(new Tuple<Move, double>(move, colour * score));
                            m_Zasher.AddIfBetter(b, new Tuple<int, double>(depth, colour * score));
                        }
                    }
                }

                return alpha;
            }
        }