/// <summary>
        /// Read games from chess games format.
        /// </summary>
        /// <param name="filePath">The file path of the chess games file.</param>
        /// <returns>a list of chess games</returns>
        public IEnumerable <ChessGame> Deserialize(string filePath)
        {
            var games = new List <ChessGame>();

            using (var reader = new StreamReader(filePath))
            {
                string buffer;

                while ((buffer = reader.ReadLine()) != null)
                {
                    var game = new ChessGame();

                    // parse winner
                    char winnerContent = buffer[buffer.IndexOf('w') + 2];
                    buffer = buffer.Substring(0, buffer.LastIndexOf(','));

                    switch (winnerContent)
                    {
                    case 'w': game.Winner = ChessColor.White; break;

                    case 'b': game.Winner = ChessColor.Black; break;

                    default:  game.Winner = null;             break;
                    }

                    // parse the draws and apply them to the game
                    var drawsOfGame = buffer.Trim().Split(',').Select(x => new ChessDraw(int.Parse(x.Trim(), System.Globalization.NumberStyles.HexNumber))).ToList();
                    drawsOfGame.ForEach(x => game.ApplyDraw(x));

                    games.Add(game);
                }
            }

            return(games);
        }
        /// <summary>
        /// <para>Compute the win rate of each (board, draw) tuple onto the given chess games by grouping those tuples for multiple games.</para>
        /// WARNING: This function might use lots of RAM to speed up the computation!!! (about 11 GB for evaluating 360000 games)
        /// </summary>
        /// <param name="games">The chess games to be evaluated.</param>
        /// <returns>a list of win rates for each (board, draw) tuple onto the given chess games</returns>
        public IEnumerable <WinRateInfo> GamesToWinRates(IEnumerable <ChessGame> games)
        {
            // TODO: use Trill API here ... instead of Linq ...

            var drawsCache = games.Where(game => game.Winner != null).AsParallel().SelectMany(game => {
                var drawsXWinner = new List <Tuple <Tuple <string, ChessDraw>, ChessColor> >();

                var winningSide = game.Winner.Value;
                var tempGame    = new ChessGame();

                foreach (var draw in game.AllDraws)
                {
                    var board = (IChessBoard)((ICloneable)tempGame.Board).Clone();
                    drawsXWinner.Add(new Tuple <Tuple <string, ChessDraw>, ChessColor>(new Tuple <string, ChessDraw>(board.ToHash(), draw), winningSide));
                    tempGame.ApplyDraw(draw);
                }

                return(drawsXWinner);
            }).ToList();

            var winRates = drawsCache.GroupBy(x => x.Item1).Where(x => x.Count() >= 5).AsParallel().Select(group => {
                int drawingSideWins = group.Count(x => x.Item2 == group.Key.Item2.DrawingSide);
                int totalGames      = group.Count();

                double winRate = (double)drawingSideWins / totalGames;
                return(new WinRateInfo()
                {
                    Draw = group.Key.Item2, BoardHash = group.Key.Item1, WinRate = winRate, AnalyzedGames = totalGames
                });
            })
                           .ToList();

            return(winRates);
        }
        /// <summary>
        /// Start a new game with the two players of the session and continue until the game is over.
        /// </summary>
        /// <returns>return the chess game log with all draws etc.</returns>
        public ChessGame ExecuteGame()
        {
            // initialize new chess game
            Game = new ChessGame();

            // continue until the game is over
            while (!Game.GameStatus.IsGameOver())
            {
                // determin the drawing player
                var drawingPlayer = Game.SideToDraw == ChessColor.White ? WhitePlayer : BlackPlayer;

                // init loop variables
                bool      isDrawValid;
                ChessDraw draw;

                do
                {
                    // get the draw from the player
                    draw        = drawingPlayer.GetNextDraw(Game.Board, Game.LastDrawOrDefault);
                    isDrawValid = Game.ApplyDraw(draw, true);
                }while (!isDrawValid);

                // raise board changed event
                BoardChanged?.Invoke(Game.Board);
            }

            // return the chess game, so it can be logged, etc.
            return(Game);
        }
Esempio n. 4
0
        /// <summary>
        /// Retrieve the chess game data from a single PGN game log.
        /// </summary>
        /// <param name="log">The PGN game log to be parsed.</param>
        /// <returns>The chess game data to was parsed.</returns>
        private ChessGame parseGameLog(string log)
        {
            var game = new ChessGame();

            log = log.Trim();

            int i           = 0;
            int nextComment = log.IndexOf('{');

            // parse all draws of the game log
            while (i < log.Length)
            {
                // determine the start and end of the draw data to be parsed
                int start = log.IndexOf('.', i) + 1;
                int end   = (log.IndexOf('.', start) > 0) ? (log.IndexOf('.', start) - 1) : (log.Length);

                // get text of the draw data (usually 1 or 2 draws)
                string drawText = ((end > 0) ? log.Substring(start, end - start) : log.Substring(start)).Trim();

                // ignore comments
                if (nextComment > 0 && end > nextComment)
                {
                    int commentEnd = log.IndexOf('}', nextComment);
                    end         = (log.IndexOf('.', commentEnd) > 0) ? (log.IndexOf('.', commentEnd) - 1) : (log.Length);
                    drawText    = log.Substring(start, nextComment - start).Trim() + log.Substring(commentEnd + 1, end - commentEnd - 1);
                    nextComment = log.IndexOf('{', commentEnd);
                }

                // parse draws of this round (each white and black side)
                var draws = parseRound(game, drawText);

                // apply white and black draw to the chess board
                foreach (var draw in draws)
                {
                    game.ApplyDraw(draw);
                }

                // stop if there was a parsing error / no draw content is left to be parsed
                if (draws?.Count() == 0)
                {
                    break;
                }

                // update index
                i = end;
            }

            // determine the winning side
            int    gameSeriesScoreIndex = log.LastIndexOf(" ") + 1;
            string gameSeriesScore      = log.Substring(gameSeriesScoreIndex, log.Length - gameSeriesScoreIndex);

            game.Winner = gameSeriesScore.Equals("1-0") ? ChessColor.White : (gameSeriesScore.Equals("0-1") ? (ChessColor?)ChessColor.Black : null);
            // TODO: extend parser logic for game scores other than '1-0', '0-1' and '1/2, 1/2'

            return(game);
        }
Esempio n. 5
0
        /// <summary>
        /// Try to submit the a chess draw if it is valid.
        /// </summary>
        /// <param name="draw">The draw to be submitted</param>
        /// <returns>a boolean indicating whether the submitted chess draw is valid</returns>
        public bool TrySubmitDraw(ChessDraw draw)
        {
            // try to apply the chess draw
            bool success = _game.ApplyDraw(draw, true);

            // release the mutex of the waiting
            if (success && _isWaiting)
            {
                _isWaiting = false;
                _mutexWait.ReleaseMutex();
            }

            return(success);
        }
        private ChessGame prepareGame(List <Tuple <ChessPosition, ChessPosition> > moves)
        {
            // init a chess board in start formation
            var       game     = new ChessGame();
            ChessDraw lastDraw = new ChessDraw();

            // apply the moves to the chess board
            foreach (var move in moves)
            {
                lastDraw = new ChessDraw(game.Board, move.Item1, move.Item2);
                game.ApplyDraw(lastDraw);

                var status = ChessDrawSimulator.Instance.GetCheckGameStatus(game.Board, lastDraw);
                Assert.True(status == ChessGameStatus.Check || status == ChessGameStatus.None);
            }

            return(game);
        }