/// <summary>
        /// Gets the next move.
        /// </summary>
        /// <param name="fen">The board configuration.</param>
        /// <param name="repetitionMoveCandidate">
        /// The move that, if made, it will result a draw by repetition. 
        /// The engine will try to avoid the move if there is a better one.
        /// </param>
        /// <param name="depth">Search depth level.</param>
        /// <returns></returns>
        public string GetNextMove(string fen, string repetitionMoveCandidate, int depth)
        {
            // the engine is still thinking, return
            if (thinking) { return null; }

            // initialize the engine
            try
            {
                Initialize(fen);
            }
            catch
            {
                return null;
            }

               int hash;

            // look in the opening book (OBookMem.cs) in memory buffer...

            short obMove=0;
            if (moves <= Settings_Default_OpeningBookMaxMoveNo) obMove=obookmem.OBookGet(hash = GetHashCode());
            if(obMove>0)
                {
                Move move = new Move();
                move.from = (byte)(obMove>> 8);
                move.to = (byte)(obMove & 255);

                return move.ToString();
                }

            // look in the opening book

               if (book != null && moves <= Settings_Default_OpeningBookMaxMoveNo && book.ContainsKey(hash = GetHashCode()))
               {
                // get the list of available moves for this board
                List<short> list = book[hash];

                //return a random move from the list
                short shortMove = list[random.Next(list.Count)];

                Move move = new Move();
                move.from = (byte)(shortMove >> 8);
                move.to = (byte)(shortMove & 255);

                return move.ToString();
            }
            else
            {
                // set repetition move
                // a repetition move cannot be a promotion move, a castling move, a capture move or a pawn move
                // so the move bits and capture are 0
                repMove = Move.ParseRegularCAN(repetitionMoveCandidate);

                // the depth must be between 1 and ChessEngineMaxDepth
                if (depth < 1)
                    depth = 1;
                else if (depth > Settings_Default_ChessEngineMaxDepth)
                    depth = Settings_Default_ChessEngineMaxDepth;
            //                else if (depth > Settings.Default.ChessEngineMaxDepth)
            //                    depth = Settings.Default.ChessEngineMaxDepth;

            // search
                try
                {
                    thinking = true;
                    Think(depth);
                }
                catch
                {
                    // the search has ended abruptly or something went wrong
                }
                finally
                {
                    thinking = false;
                }

                // pv[0, 0] is the best move
                return pv[0, 0].ToString();
               }
        }