private IgsCode ExtractCodeFromLine(string line)
 {
     if (line != "")
     {
         string[] split     = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
         string   firstWord = split[0];
         int      firstWordAsInteger;
         if (int.TryParse(firstWord, out firstWordAsInteger))
         {
             IgsCode code = (IgsCode)firstWordAsInteger;
             return(code);
         }
     }
     return(IgsCode.Unknown);
 }
        private async Task HandleIncomingData(StreamReader sr)
        {
            bool           thisIsNotAMove           = false;
            bool           weAreHandlingAnInterrupt = false;
            bool           interruptIsImpossible    = false;
            List <IgsLine> currentLineBatch         = new List <IgsLine>();

            while (true)
            {
                string line;
                try
                {
                    line = await sr.ReadLineAsync();
                }
                catch (Exception)
                {
                    line = null;
                }
                if (line == null)
                {
                    ConnectionLost();
                    return;
                }
                line = line.Trim();


                IgsCode code    = ExtractCodeFromLine(line);
                IgsLine igsLine = new IgsLine(code, line);
                Events.OnIncomingLine((weAreHandlingAnInterrupt ? "(INTERRUPT) " : "") + (interruptIsImpossible ? "(INTERRUPT IMPOSSIBLE) " : "") + line);

                // IGS occasionally sends blank lines, I don't know why. They serve no reason.
                if (line == "")
                {
                    continue;
                }

                switch (this.Composure)
                {
                case IgsComposure.Confused:
                case IgsComposure.Ok:
                case IgsComposure.Disconnected:
                    // No special mode.
                    break;

                case IgsComposure.InitialHandshake:
                    if (igsLine.EntireLine.Trim() == "1 5")
                    {
                        this.Composure = IgsComposure.Ok;
                        continue;
                    }
                    else
                    {
                        // Ignore.
                        continue;
                    }

                case IgsComposure.LoggingIn:
                    if (igsLine.EntireLine.Contains("Invalid password."))
                    {
                        this.Composure   = IgsComposure.Confused;
                        this._loginError = "The password is incorrect.";
                        continue;
                    }
                    if (igsLine.EntireLine.Contains("Sorry, names can be"))
                    {
                        this.Composure   = IgsComposure.Confused;
                        this._loginError = "Your name is too long.";
                        continue;
                    }
                    if (igsLine.EntireLine.Contains("This is a guest account."))
                    {
                        this.Composure   = IgsComposure.Confused;
                        this._loginError = "The username does not exist.";
                        continue;
                    }
                    if (igsLine.EntireLine.Contains("1 5"))
                    {
                        this.Composure = IgsComposure.Ok;
                        continue;
                    }
                    break;
                }

                if (igsLine.Code == IgsCode.Error)
                {
                    Events.OnErrorMessageReceived(igsLine.PureLine);
                }
                currentLineBatch.Add(igsLine);

                if (weAreHandlingAnInterrupt && code == IgsCode.Prompt)
                {
                    // Interrupt message is over, let's wait for a new message
                    weAreHandlingAnInterrupt = false;
                    HandleFullInterrupt(currentLineBatch);
                    thisIsNotAMove        = false;
                    interruptIsImpossible = false;
                    currentLineBatch      = new List <IgsLine>();
                    continue;
                }
                if (code == IgsCode.Prompt)
                {
                    thisIsNotAMove        = false;
                    currentLineBatch      = new List <IgsLine>();
                    interruptIsImpossible = false;
                    if (this._ignoreNextPrompt)
                    {
                        this._ignoreNextPrompt = false;
                        continue;
                    }
                }
                if (code == IgsCode.Kibitz)
                {
                    weAreHandlingAnInterrupt = true;
                    continue;
                }
                if (code == IgsCode.Beep)
                {
                    Events.OnBeep();
                    continue;
                }

                if (!interruptIsImpossible)
                {
                    if (code == IgsCode.Tell)
                    {
                        if (igsLine.PureLine.StartsWith("*SYSTEM*"))
                        {
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        HandleIncomingChatMessage(line);
                        weAreHandlingAnInterrupt = true;
                        continue;
                    }
                    if (code == IgsCode.SayInformation)
                    {
                        weAreHandlingAnInterrupt = true;
                        continue;
                    }
                    if (code == IgsCode.Status)
                    {
                        weAreHandlingAnInterrupt = true;
                        continue;
                    }
                    if (code == IgsCode.Shout)
                    {
                        HandleIncomingShoutMessage(line);
                        weAreHandlingAnInterrupt = true;
                        continue;
                    }
                    if (code == IgsCode.StoneRemoval)
                    {
                        Tuple <int, Position> removedStone = IgsRegex.ParseStoneRemoval(igsLine);
                        OnIncomingStoneRemoval(removedStone.Item1, removedStone.Item2);
                        continue;
                    }
                    if (code == IgsCode.Move)
                    {
                        var heading = IgsRegex.ParseGameHeading(igsLine);
                        if (heading != null)
                        {
                            this.Data.LastReceivedGameHeading = heading;
                        }
                        if (!thisIsNotAMove)
                        {
                            HandleIncomingMove(igsLine);
                            weAreHandlingAnInterrupt = true;
                        }
                        continue;
                    }
                    if (code == IgsCode.Undo)
                    {
                        thisIsNotAMove           = true;
                        weAreHandlingAnInterrupt = true;
                        continue;
                    }
                }
                if (code == IgsCode.Info)
                {
                    // 9 Adding game to observation list.
                    if (igsLine.EntireLine.Contains("9 Adding game to observation list."))
                    {
                        interruptIsImpossible = true;
                    }
                    if (!interruptIsImpossible)
                    {
                        if (igsLine.PureLine == "yes")
                        {
                            // This is "ayt" response, ignore it.
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }

                        if (igsLine.EntireLine ==
                            "9 You can check your score with the score command, type 'done' when finished.")
                        {
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (igsLine.PureLine.Contains("accepted."))
                        {
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (igsLine.PureLine.Contains("Removing @"))
                        {
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (igsLine.PureLine.Contains("has run out of time"))
                        {
                            weAreHandlingAnInterrupt = true;
                            string whoRanOutOfTime = IgsRegex.WhoRanOutOfTime(igsLine);
                            foreach (var game in GetGamesIncluding(whoRanOutOfTime).ToList())
                            {
                                game.Controller.IgsConnector.EndTheGame(
                                    GameEndInformation.CreateTimeout(
                                        game.Controller.Players.First(pl => pl.Info.Name == whoRanOutOfTime),
                                        game.Controller.Players)
                                    );
                            }
                            continue;
                        }
                        if (igsLine.PureLine.Contains("White resigns.}"))
                        {
                            int gameInWhichSomebodyResigned = IgsRegex.WhatObservedGameWasResigned(igsLine);
                            ResignObservedGame(gameInWhichSomebodyResigned, StoneColor.White);
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (igsLine.PureLine.Contains("Black resigns.}"))
                        {
                            int gameInWhichSomebodyResigned = IgsRegex.WhatObservedGameWasResigned(igsLine);
                            ResignObservedGame(gameInWhichSomebodyResigned, StoneColor.Black);
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (igsLine.PureLine.Contains("has resigned the game"))
                        {
                            string whoResigned = IgsRegex.WhoResignedTheGame(igsLine);
                            if (whoResigned != this._username)
                            {
                                // .ToList() is used because the collection may be modified
                                foreach (var game in GetGamesIncluding(whoResigned).ToList())
                                {
                                    HandleIncomingResignation(game.Info, whoResigned);
                                }
                            }
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (igsLine.PureLine.Contains("has typed done."))
                        {
                            string username = IgsRegex.GetFirstWord(igsLine);
                            weAreHandlingAnInterrupt = true;
                            foreach (var game in GetGamesIncluding(username))
                            {
                                var player = game.Controller.Players.First(pl => pl.Info.Name == username);
                                game.Controller.IgsConnector.RaiseServerSaidDone(player);
                            }
                            continue;
                        }
                        if (igsLine.PureLine.Contains("Board is restored to what it was when you started scoring"))
                        {
                            foreach (
                                var game in
                                this.GamesYouHaveOpened.Where(
                                    gi =>
                                    gi.Controller.Phase.Type ==
                                    GamePhaseType.LifeDeathDetermination))
                            {
                                GetConnector(game.Info).ForceLifeDeathUndoDeathMarks();
                            }
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }

                        if (igsLine.PureLine.Contains("Removed game file"))
                        {
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (igsLine.PureLine.Contains("game completed."))
                        {
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (igsLine.PureLine.StartsWith("!!*Pandanet*!!:"))
                        {
                            // Advertisement
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (IgsRegex.IsIrrelevantInterruptLine(igsLine))
                        {
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                        if (igsLine.PureLine.StartsWith("Increase "))
                        {
                            weAreHandlingAnInterrupt = true;
                            string person = IgsRegex.ParseIncreaseXTimeByYMinute(igsLine);
                            foreach (var game in this.GamesYouHaveOpened)
                            {
                                if (game.Info.Black.Name == person ||
                                    game.Info.White.Name == person)
                                {
                                    MakeUnattendedRequest("refresh " + game.Info.IgsIndex);
                                }
                            }
                        }

                        if (igsLine.PureLine.EndsWith("declines undo."))
                        {
                            string username = IgsRegex.WhoDeclinesUndo(igsLine);
                            foreach (var game in GetGamesIncluding(username))
                            {
                                Events.OnUndoDeclined(game.Info);
                            }
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }

                        if (igsLine.PureLine.EndsWith("declines your request for a match."))
                        {
                            Events.OnMatchRequestDeclined(igsLine.PureLine.Substring(0, igsLine.PureLine.IndexOf(' ')));
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }

                        IgsMatchRequest matchRequest = IgsRegex.ParseMatchRequest(igsLine);
                        if (matchRequest != null)
                        {
                            this._incomingMatchRequests.Add(matchRequest);
                            Events.OnIncomingMatchRequest(matchRequest);
                            weAreHandlingAnInterrupt = true;
                            continue;
                        }
                    }
                }

                if (!weAreHandlingAnInterrupt)
                {
                    // We cannot handle this generally - let's hand it off to whoever made the request for this information.
                    lock (this._mutex)
                    {
                        if (this._requestInProgress != null)
                        {
                            this._requestInProgress.IncomingLines.Post(igsLine);
                        }
                        else
                        {
                            if (this.Composure == IgsComposure.Ok)
                            {
                                Events.OnUnhandledLine(igsLine.EntireLine);
                            }
                        }
                    }
                }
            }
        }
示例#3
0
 public IgsLine(IgsCode code, string line)
 {
     Code       = code;
     EntireLine = line;
 }