/// <summary> /// In local game we are in control of time, clock out the player /// </summary> /// <param name="player">Player the clocked out</param> protected override bool HandleLocalClockOut(GamePlayer player) { var endGameInformation = GameEndInformation.CreateTimeout(player, Controller.Players); Controller.EndGame(endGameInformation); return(true); }
public override void Process(KgsConnection connection) { var game = connection.Data.GetGame(ChannelId); var controller = game.Controller; var players = game.Controller.Players; var black = game.Controller.Players.Black; var white = game.Controller.Players.White; GameEndInformation gameEndInfo = null; if (Score.IsFloat) { if (Score.Float == 0) { gameEndInfo = GameEndInformation.CreateDraw(controller.Players, new Rules.Scores(0, 0)); } else { if (Score.Float > 0) { gameEndInfo = GameEndInformation.CreateScoredGame(controller.Players.Black, controller.Players.White, new Rules.Scores(Score.Float, 0)); } else { gameEndInfo = GameEndInformation.CreateScoredGame(controller.Players.White, controller.Players.Black, new Rules.Scores(0, -Score.Float)); } } } else { switch (Score.String) { case "B+RESIGN": case "B+FORFEIT": gameEndInfo = GameEndInformation.CreateResignation(white, players); break; case "W+RESIGN": case "W+FORFEIT": gameEndInfo = GameEndInformation.CreateResignation(black, players); break; case "B+TIME": gameEndInfo = GameEndInformation.CreateTimeout(white, players); break; case "W+TIME": gameEndInfo = GameEndInformation.CreateTimeout(black, players); break; case "NO_RESULT": gameEndInfo = GameEndInformation.CreateDraw(players, new Rules.Scores(0, 0)); break; case "UNKNOWN": case "UNFINISHED": default: gameEndInfo = GameEndInformation.CreateCancellation(players); break; } } controller.KgsConnector.EndTheGame(gameEndInfo); }
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); } } } } } }