//returns true if AI will win
        private bool simulatePerfectGame(MCTSNode_QAI currNode)
        {
            MCTSNode_QAI bestMove = null;

            if (currNode.flag[qflags.CHILDHASLOSINGBOARD])
            {
                return(false);
            }
            else if (currNode.flag[qflags.CHILDHASWINNINGBOARD])
            {
                return(true);
            }
            else if (currNode.flag[qflags.ENDBOARD])
            {
                if (currNode.flag[qflags.OWNER])
                {
                    return(currNode.isWinState());
                }
                else
                {
                    return(currNode.isTie());
                }
            }

            for (int index = 0; index < currNode.children.Count; index++)
            {
                if (currNode.children[index].flag[qflags.OWNER] &&
                    (bestMove == null ||
                     bestMove.nodePickScore() < currNode.children[index].nodePickScore()))
                {
                    bestMove = currNode.children[index];
                }
                else if (!currNode.children[index].flag[qflags.OWNER] &&
                         (bestMove == null ||
                          bestMove.nodePickScore() > currNode.children[index].nodePickScore()))
                {
                    bestMove = currNode.children[index];
                }
            }

            return(simulatePerfectGame(bestMove));
        }
        public Tuple <byte, byte> AIFullTurn_debug(byte givenPiece, byte boardPosition)
        {
            MCTSNode_QAI temp = null;
            byte         pieceToGive;
            byte         positionToPlace = 255;

            if (this.root != null && this.root.flag[qflags.ENDBOARD])
            {
                return(new Tuple <byte, byte>(255, 255));
            }

            if (AITurnUpkeep(givenPiece, boardPosition) == null)
            {
                temp = AITurnPart(2000);

                /*DEBUG*/
                Console.WriteLine("\n\nSummary:");
                /*DEBUG*/
                Console.WriteLine("Counter: ");
                /*DEBUG*/
                Console.WriteLine("Root: " + root.nodeValue + " " + root.score.Item1 + " " + root.score.Item2 + " " + counter);
                /*DEBUG*/
                for (int i = 0; i < root.children.Count; i++)
                /*DEBUG*/
                {
                    /*DEBUG*/
                    Console.WriteLine("Child" + i + ": " + root.children[i].nodeValue + " " + root.children[i].score.Item1 + " " + root.children[i].score.Item2 + " " + Math.Round((float)root.children[i].nodePickScore(), 4) + " " + Math.Round((float)root.children[i].nodeSimScore(root.score.Item2), 4));
                    /*DEBUG*/
                }

                this.root       = temp;
                positionToPlace = this.root.nodeValue;
                temp            = AITurnPart(2000);

                /*DEBUG*/
                Console.WriteLine("\n\nSummary:");
                /*DEBUG*/
                Console.WriteLine("Counter: ");
                /*DEBUG*/
                Console.WriteLine("Root: " + root.nodeValue + " " + root.score.Item1 + " " + root.score.Item2 + " " + counter);
                /*DEBUG*/
                for (int i = 0; i < root.children.Count; i++)
                /*DEBUG*/
                {
                    /*DEBUG*/
                    Console.WriteLine("Child" + i + ": " + root.children[i].nodeValue + " " + root.children[i].score.Item1 + " " + root.children[i].score.Item2 + " " + Math.Round((float)root.children[i].nodePickScore(), 4) + " " + Math.Round((float)root.children[i].nodeSimScore(root.score.Item2), 4));
                    /*DEBUG*/
                }

                if (temp != null)
                {
                    this.root   = temp;
                    pieceToGive = this.root.nodeValue;
                    /*DEBUG*/
                    Console.WriteLine("Selected: " + root.nodeValue + " with score " + root.nodePickScore());
                }
                else
                {
                    pieceToGive = 0;
                }

                time.Stop();
                return(new Tuple <byte, byte>(positionToPlace, pieceToGive));
            }
            else
            {
                time.Stop();
                return(new Tuple <byte, byte>(positionToPlace, this.root.nodeValue));
            }
        }
        //Selects best move and returns reference to its noded
        private MCTSNode_QAI selectBestMove(MCTSNode_QAI currNode)
        {
            MCTSNode_QAI selectedMove = null;
            bool         gameWin      = false;

            if (this.difficulty == diff.hard)
            {
                bool willWinPerfectGame = false;
                for (int index = 0; index < currNode.children.Count && !gameWin; index++)
                {
                    if (!willWinPerfectGame)
                    {
                        if (selectedMove == null)
                        {
                            selectedMove       = currNode.children[index];
                            willWinPerfectGame = simulatePerfectGame(currNode.children[index]);
                        }
                        else
                        {
                            willWinPerfectGame = simulatePerfectGame(currNode.children[index]);
                            if (willWinPerfectGame || selectedMove.nodePickScore() < currNode.children[index].nodePickScore())
                            {
                                selectedMove = currNode.children[index];
                            }
                        }
                    }
                    else
                    {
                        if (currNode.children[index].flag[qflags.ENDBOARD])
                        {
                            selectedMove = currNode.children[index];
                            gameWin      = true;
                        }
                        else if (selectedMove.nodePickScore() < currNode.children[index].nodePickScore())
                        {
                            if (simulatePerfectGame(currNode.children[index]))
                            {
                                selectedMove = currNode.children[index];
                            }
                        }
                    }
                }
            }
            else
            {
                for (int index = 0; index < currNode.children.Count && !gameWin; index++)
                {
                    if (compareMove())
                    {
                        if (selectedMove == null)
                        {
                            selectedMove = currNode.children[index];
                        }
                        if (currNode.children[index].flag[qflags.ENDBOARD])
                        {
                            selectedMove = currNode.children[index];
                            gameWin      = true;
                        }
                        else if (selectedMove.nodePickScore() < currNode.children[index].nodePickScore())
                        {
                            selectedMove = currNode.children[index];
                        }
                    }
                }
            }

            if (selectedMove == null && currNode.children.Count > 0)
            {
                selectedMove = currNode.children[random.Next(0, currNode.children.Count)];
            }

            return(selectedMove);
        }