private void HandleIncomingMove(IgsLine igsLine)
        {
            string      trim    = igsLine.PureLine.Trim();
            GameHeading heading = IgsRegex.ParseGameHeading(igsLine);

            if (heading != null)
            {
                IgsGame whatGame = this.GamesYouHaveOpened.Find(gm => gm.Info.IgsIndex == heading.GameNumber);
                if (whatGame == null)
                {
                    // Do not remember this game, perhaps we're in match accept procedure
                    return;
                }
                _incomingMovesAreForThisGame = whatGame;
                GetConnector(whatGame.Info).TimeControlAdjustment(new IgsTimeControlAdjustmentEventArgs(heading.WhiteTimeRemaining, heading.BlackTimeRemaining));
            }
            else if (trim.Contains("Handicap"))
            {
                //  15   0(B): Handicap 3
                int handicapStones = IgsRegex.ParseHandicapMove(igsLine);
                OnIncomingHandicapInformation(_incomingMovesAreForThisGame, handicapStones);
            }
            else
            {
                Match      match       = this._regexMove.Match(trim);
                string     moveIndex   = match.Groups[1].Value;
                string     mover       = match.Groups[2].Value;
                string     coordinates = match.Groups[3].Value;
                string     captures    = match.Groups[4].Value;
                StoneColor moverColor  = mover == "B" ? StoneColor.Black : StoneColor.White;
                Move       move;
                if (coordinates == "Pass")
                {
                    move = Move.Pass(moverColor);
                }
                else
                {
                    move = Move.PlaceStone(moverColor,
                                           Position.FromIgsCoordinates(coordinates));
                }
                string[] captureSplit = captures.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string capture in captureSplit)
                {
                    move.Captures.Add(Position.FromIgsCoordinates(capture));
                }
                HandleIncomingMove(_incomingMovesAreForThisGame, int.Parse(moveIndex), move);
            }
        }
        private async void HandleFullInterrupt(List <IgsLine> currentLineBatch)
        {
            if (currentLineBatch.Count > 0)
            {
                if (currentLineBatch.Any(line => line.Code == IgsCode.Status))
                {
                    var infoLine = currentLineBatch.FirstOrDefault(ln => ln.Code == IgsCode.Info);
                    if (infoLine != null)
                    {
                        ScoreLine scoreLine = IgsRegex.ParseObservedScoreLine(infoLine);
                        if (scoreLine != null)
                        {
                            IgsGame gameInfo = this.GamesYouHaveOpened.FirstOrDefault(gi => gi.Info.IgsIndex == scoreLine.GameId);
                            if (gameInfo != null)
                            {
                                ScoreGame(gameInfo, scoreLine.BlackScore, scoreLine.WhiteScore);
                            }
                        }
                    }
                }
                if (currentLineBatch.Any(line => line.PureLine.EndsWith("accepted.") && line.Code == IgsCode.Info))
                {
                    // An outgoing match request has been accepted by another player and the game can begin.
                    GameHeading heading = this.Data.LastReceivedGameHeading;
                    var         ogi     = await Commands.GetGameByIdAsync(heading.GameNumber);

                    var  builder     = GameBuilder.CreateOnlineGame(ogi).Connection(this);
                    bool youAreBlack = ogi.Black.Name == _username;
                    bool youAreWhite = ogi.White.Name == _username;
                    if (youAreBlack)
                    {
                        builder.BlackPlayer(
                            new HumanPlayerBuilder(StoneColor.Black)
                            .Name(ogi.Black.Name)
                            .Rank(ogi.Black.Rank)
                            .Clock(new CanadianTimeControl(TimeSpan.Zero, 25, TimeSpan.FromMinutes(ogi.ByoyomiPeriod)).UpdateFrom(heading.BlackTimeRemaining))
                            .Build());
                    }
                    else
                    {
                        builder.BlackPlayer(
                            new IgsPlayerBuilder(StoneColor.Black, this)
                            .Name(ogi.Black.Name)
                            .Rank(ogi.Black.Rank)
                            .Clock(new CanadianTimeControl(TimeSpan.Zero, 25, TimeSpan.FromMinutes(ogi.ByoyomiPeriod)).UpdateFrom(heading.BlackTimeRemaining))
                            .Build());
                    }
                    if (youAreWhite)
                    {
                        builder.WhitePlayer(
                            new HumanPlayerBuilder(StoneColor.White)
                            .Name(ogi.White.Name)
                            .Rank(ogi.White.Rank)
                            .Clock(new CanadianTimeControl(TimeSpan.Zero, 25, TimeSpan.FromMinutes(ogi.ByoyomiPeriod)).UpdateFrom(heading.WhiteTimeRemaining))
                            .Build());
                    }
                    else
                    {
                        builder.WhitePlayer(
                            new IgsPlayerBuilder(StoneColor.White, this)
                            .Name(ogi.White.Name)
                            .Rank(ogi.White.Rank)
                            .Clock(new CanadianTimeControl(TimeSpan.Zero, 25, TimeSpan.FromMinutes(ogi.ByoyomiPeriod)).UpdateFrom(heading.WhiteTimeRemaining))
                            .Build());
                    }
                    IgsGame newGame = builder.Build();
                    this.GamesYouHaveOpened.Add(newGame);
                    Events.OnMatchRequestAccepted(newGame);
                }

                if (currentLineBatch.Any(line => line.PureLine.Contains("Creating match") && line.Code == IgsCode.Info))
                {
                    // Make it not be an interrupt and let it be handled by the match creator.
                    foreach (IgsLine line in currentLineBatch)
                    {
                        lock (this._mutex)
                        {
                            if (this._requestInProgress != null)
                            {
                                this._requestInProgress.IncomingLines.Post(line);
                            }
                            else
                            {
                                if (this.Composure == IgsComposure.Ok)
                                {
                                    Events.OnUnhandledLine(line.EntireLine);
                                }
                            }
                        }
                    }
                }

                if (currentLineBatch.Count == 3 && currentLineBatch[0].Code == IgsCode.SayInformation &&
                    currentLineBatch[1].Code == IgsCode.Say)
                {
                    int         gameNumber   = IgsRegex.ParseGameNumberFromSayInformation(currentLineBatch[0]);
                    ChatMessage chatLine     = IgsRegex.ParseSayLine(currentLineBatch[1], this);
                    IgsGame     relevantGame = this.GamesYouHaveOpened.Find(gi => gi.Info.IgsIndex == gameNumber);
                    if (relevantGame == null)
                    {
                        // We received a chat message for a game we no longer play.
                        return;
                    }
                    if (chatLine.Text.StartsWith(gameNumber + " "))
                    {
                        chatLine.Text = chatLine.Text.Substring((gameNumber + " ").Length);
                    }

                    GetConnector(relevantGame.Info).ChatMessageFromServer(chatLine);
                }

                if (currentLineBatch[0].Code == IgsCode.Kibitz &&
                    currentLineBatch.Count >= 2)
                {
                    // 11 Kibitz ([^ ]+).*\[([0-9]+)\]
                    Tuple <string, int> firstLine = IgsRegex.ParseKibitzHeading(currentLineBatch[0]);
                    string  text         = currentLineBatch[1].PureLine.Trim();
                    IgsGame relevantGame = this.GamesYouHaveOpened.Find(gi => gi.Info.IgsIndex == firstLine.Item2);
                    GetConnector(relevantGame.Info).ChatMessageFromServer(new ChatMessage(firstLine.Item1,
                                                                                          text, DateTimeOffset.Now, firstLine.Item1 == this.Username ? ChatMessageKind.Outgoing : ChatMessageKind.Incoming));
                }

                if (currentLineBatch[0].Code == IgsCode.Tell &&
                    currentLineBatch[0].PureLine.StartsWith("*SYSTEM*") &&
                    currentLineBatch[0].PureLine.EndsWith("requests undo."))
                {
                    string requestingUser = IgsRegex.WhoRequestsUndo(currentLineBatch[0]);
                    var    games          = GetGamesIncluding(requestingUser);
                    if (games.Any())
                    {
                        foreach (var game in games)
                        {
                            Events.OnUndoRequestReceived(game.Info);
                        }
                    }
                    else
                    {
                        throw new Exception("Received an undo request for a game that's not in progress.");
                    }
                    this._ignoreNextPrompt = true;
                }
                if (currentLineBatch[0].Code == IgsCode.Undo)
                {
                    int     numberOfMovesToUndo = currentLineBatch.Count(line => line.Code == IgsCode.Undo);
                    IgsLine gameHeadingLine     = currentLineBatch.Find(line => line.Code == IgsCode.Move);
                    int     game     = IgsRegex.ParseGameNumberFromHeading(gameHeadingLine);
                    IgsGame gameInfo = this.GamesYouHaveOpened.Find(gi => gi.Info.IgsIndex == game);
                    for (int i = 0; i < numberOfMovesToUndo; i++)
                    {
                        GetConnector(gameInfo.Info).ForceMainUndo();
                    }
                }

                if (currentLineBatch[0].EntireLine.Contains("'done'"))
                {
                    IgsLine gameHeadingLine = currentLineBatch.Find(line => line.Code == IgsCode.Move);
                    int     gameIndex       = IgsRegex.ParseGameNumberFromHeading(gameHeadingLine);
                    _availableConnectors[gameIndex].SetPhaseFromServer(GamePhaseType.LifeDeathDetermination);
                }
                if (currentLineBatch.Any(ln => ln.Code == IgsCode.Score))
                {
                    ScoreLine scoreLine = IgsRegex.ParseScoreLine(currentLineBatch.Find(ln => ln.Code == IgsCode.Score));
                    IgsGame   gameInfo  = this.GamesYouHaveOpened.Find(gi =>
                                                                       gi.Info.White.Name == scoreLine.White &&
                                                                       gi.Info.Black.Name == scoreLine.Black);
                    ScoreGame(gameInfo, scoreLine.BlackScore, scoreLine.WhiteScore);
                }
            }
        }