/// <summary>
        /// Traverses the PGN move text section, adding the moves to the model.
        /// Throws ArgumentException if there is an illegal SAN move.
        /// </summary>
        /// <param name="tr">The texr reader which is read from</param>
        private void TraversePGNMovetext(TextReader tr)
        {
            string line;
            int index, from, to;

            // skip the empty lines
            do
            {
                line = tr.ReadLine();
            }
            while (line != null && line.Length == 0);

            // read the lines
            while (line != null && line.Length > 0)
            {
                // it's an escape line, skip it
                if (line[0] == '%')
                {
                    line = tr.ReadLine();
                    continue;
                }

                index = 0;

                // loop through the line characters
                while (index < line.Length)
                {
                    // skip the white spaces
                    if (line[index] == ' ')
                    {
                        while (++index < line.Length && line[index] == ' ') ;
                    }

                    // it's a "rest of line" comment, go to the next line
                    if (index < line.Length && line[index] == ';')
                    {
                        line = tr.ReadLine();
                        index = 0;
                        continue;
                    }

                    // skip the move numbers, the NAG or the game termination tokens
                    if (index < line.Length && ((line[index] >= '0' && line[index] <= '9') || line[index] == '$' || line[index] == '*'))
                    {
                        while (++index < line.Length && line[index] != ' ') ;
                    }
                    // skip the multiline commentaries
                    else if (index < line.Length && line[index] == '{')
                    {
                        while (line[index++] != '}')
                        {
                            if (index >= line.Length)
                            {
                                line = tr.ReadLine();
                                index = 0;
                            }
                        }

                    }
                    // skip the RAV which can be nested
                    else if (index < line.Length && line[index] == '(')
                    {
                        int depth = 1;

                        while (depth != 0)
                        {
                            if (++index >= line.Length)
                            {
                                line = tr.ReadLine();
                                index = 0;
                            }

                            if (line[index] == '(')
                            {
                                depth++;
                            }
                            else if (line[index] == ')')
                            {
                                depth--;
                            }
                        }

                        index++;
                    }
                    // if the token it's a move, make it
                    else if (index < line.Length)
                    {
                        from = index;

                        while (++index < line.Length && line[index] != ' ') ;

                        to = index;

                        // remove any !? annotations
                        if (line[to - 1] == '!' || line[to - 1] == '?')
                        {
                            to--;
                        }
                        if (line[to - 1] == '!' || line[to - 1] == '?')
                        {
                            to--;
                        }

                        // make the move
                        model.Make(Utils.GetSANMove(model, line.Substring(from, to - from)));
                    }

                }

                line = tr.ReadLine();

            }
        }