public async Task <bool> KibitzAsync(IgsGameInfo game, string chat) { if (this.igsConnection.GamesYouHaveOpened.All(g => g.Info.IgsIndex != game.IgsIndex)) { // Game is already over. return(false); } if (chat == null) { throw new ArgumentNullException(nameof(chat)); } if (chat == "") { throw new ArgumentException("Chat line must not be empty."); } if (chat.Contains("\n")) { throw new Exception("Chat lines on IGS must not contain line breaks."); } IgsResponse response; if (this.igsConnection.GamesYouHaveOpened.Count > 1) { // More than one game is opened: we must give the game id. response = await MakeRequestAsync("kibitz " + game.IgsIndex + " " + chat); } else { // We have only one game opened: game id MUST NOT be given response = await MakeRequestAsync("kibitz " + chat); } return(!response.IsError); }
public void OnIncomingResignation(IgsGameInfo gameInfo, string whoResigned) { var game = this.GamesYouHaveOpened.Find(og => og.Metadata.IgsIndex == gameInfo.IgsIndex); IncomingResignation?.Invoke(this, new Igs.GamePlayerEventArgs(game, game.Controller.Players.First(pl => pl.Info.Name == whoResigned))); this.GamesYouHaveOpened.Remove(game); }
/// <summary> /// Handles incoming resignation /// </summary> /// <param name="gameInfo">Game info</param> /// <param name="whoResigned">Name of the player who resigned</param> internal void HandleIncomingResignation(IgsGameInfo gameInfo, string whoResigned) { var stoneColor = GetStoneColorForPlayerName(gameInfo.IgsIndex, whoResigned); if (stoneColor == StoneColor.None) { throw new InvalidOperationException("The player resignation is invalid for this game"); } _availableConnectors[gameInfo.IgsIndex].ResignationFromServer(stoneColor); DestroyGame(gameInfo); }
private IgsGameInfo CreateGameFromTelnetLine(string line) { var regex = new Regex( @"7 \[ *([0-9]+)] *([^[]+) \[([^]]+)\] vs. *([^[]+) \[([^]]+)\] \( *([0-9]+) *([0-9]+) *([0-9]+) *([-0-9.]+) *([0-9]+) *([A-Z]*)\) *\( *([0-9]+)\)"); // The regex means: /* * 1 - game id * 2 - white name * 3 - white rank * 4 - black name * 5 - black rank * 6 - number of moves played * 7 - board size * 8 - handicap stones * 9 - komi points * 10 - byoyomi period * 11 - flags * 12 - number of observers */ var match = regex.Match(line); var game = new IgsGameInfo( new PlayerInfo(StoneColor.White, match.Groups[2].Value, match.Groups[3].Value), new PlayerInfo(StoneColor.Black, match.Groups[4].Value, match.Groups[5].Value), new GameBoardSize(match.Groups[7].Value.AsInteger()), RulesetType.Japanese, match.Groups[8].Value.AsInteger(), HandicapPlacementType.Fixed, match.Groups[9].Value.AsFloat(), CountingType.Territory, match.Groups[1].Value.AsInteger(), match.Groups[12].Value.AsInteger()); game.ByoyomiPeriod = match.Groups[10].Value.AsInteger(); return(game); }
internal void OnUndoDeclined(IgsGameInfo game) { UndoDeclined?.Invoke(this, game); }
internal void OnUndoRequestReceived(IgsGameInfo game) { UndoRequestReceived?.Invoke(this, game); }
protected bool Equals(IgsGameInfo other) { return(IgsIndex == other.IgsIndex && this.Black.Name == other.Black.Name && this.White.Name == other.White.Name); }
private void OnUndoDeclined(IgsGameInfo game) { UndoDeclined?.Invoke(this, game); }
private void OnLastMoveUndone(IgsGameInfo whichGame) { LastMoveUndone?.Invoke(this, whichGame); }
private void OnIncomingInGameChatMessage(IgsGameInfo relevantGame, ChatMessage chatLine) { IncomingInGameChatMessage?.Invoke(this, new Tuple <IgsGameInfo, ChatMessage>(relevantGame, chatLine)); }
private IgsConnector GetConnector(IgsGameInfo gameinfo) { return(_availableConnectors[gameinfo.IgsIndex]); }
internal void DestroyGame(IgsGameInfo gameInfo) { this.GamesYouHaveOpened.Remove(this.GamesYouHaveOpened.FirstOrDefault(g => g.Info.IgsIndex == gameInfo.IgsIndex)); // We will not delete it from _availableConnectors yet, I think it will be safer this way. // If we encounter problems, we'll deal with them then. }
public async Task UndoPleaseAsync(IgsGameInfo game) { await MakeRequestAsync("undoplease " + game.IgsIndex); }
public async Task <IgsGame> StartObserving(IgsGameInfo gameInfo) { if (this.igsConnection.GamesBeingObserved.Any(g => g.Info.IgsIndex == gameInfo.IgsIndex)) { // We are already observing this game. return(null); } var response = await MakeRequestAsync("observe " + gameInfo.IgsIndex); if (response.IsError) { // Observing failed. return(null); } var heading = response.GetGameHeading(); if (heading == null) { return(null); } if (heading.BlackName != gameInfo.Black.Name || heading.WhiteName != gameInfo.White.Name) { // It's a different game now. return(null); } TimeControl blackClock = new CanadianTimeControl(TimeSpan.Zero, 25, TimeSpan.FromMinutes(gameInfo.ByoyomiPeriod)).UpdateFrom( heading.BlackTimeRemaining); TimeControl whiteClock = new CanadianTimeControl(TimeSpan.Zero, 25, TimeSpan.FromMinutes(gameInfo.ByoyomiPeriod)).UpdateFrom( heading.WhiteTimeRemaining); if (heading.BlackTimeRemaining.PeriodStonesLeft == 0 && heading.BlackTimeRemaining.PeriodTimeLeft == TimeSpan.Zero && heading.BlackTimeRemaining.MainTimeLeft == TimeSpan.Zero) { blackClock = new NoTimeControl(); whiteClock = new NoTimeControl(); } var titleLine = response.LastOrDefault(line => line.Code == IgsCode.Info); string gameName = null; if (titleLine != null) { gameName = IgsRegex.ParseTitleInformation(titleLine); } var blackPlayer = new IgsPlayerBuilder(StoneColor.Black, this.igsConnection) .Name(gameInfo.Black.Name) .Rank(gameInfo.Black.Rank) .Clock(blackClock) .Build(); var whitePlayer = new IgsPlayerBuilder(StoneColor.White, this.igsConnection) .Name(gameInfo.White.Name) .Rank(gameInfo.White.Rank) .Clock(whiteClock) .Build(); var onlineGame = GameBuilder.CreateOnlineGame(gameInfo) .Connection(this.igsConnection) .BlackPlayer(blackPlayer) .WhitePlayer(whitePlayer) .Ruleset(RulesetType.Japanese) .Komi(gameInfo.Komi) .BoardSize(gameInfo.BoardSize) .Name(gameName) .Build(); this.igsConnection.GamesBeingObserved.Add(onlineGame); this.igsConnection.GamesYouHaveOpened.Add(onlineGame); this.igsConnection.MakeUnattendedRequest("moves " + gameInfo.IgsIndex); return(onlineGame); }