public Task <VariationLine> CreateGetMoveTask(GetMoveRequest request)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (request.Board.ActiveSide != Side)
            {
                throw new ArgumentException(
                          $@"The board's active side '{request.Board.ActiveSide
                        }' is inconsistent with the player's side '{Side}'.",
                          nameof(request));
            }

            if (request.Board.ValidMoves.Count == 0)
            {
                throw new ArgumentException("There are no valid moves.", nameof(request));
            }

            var result = new Task <VariationLine>(() => DoGetMove(request), request.CancellationToken);

            OnGetMoveTaskCreated(result, request.CancellationToken);
            return(result);
        }
 protected abstract VariationLine DoGetMove([NotNull] GetMoveRequest request);
Example #3
0
        private void ExecuteGameInternal()
        {
            var currentMethodName = MethodBase.GetCurrentMethod().GetQualifiedName();

            while (!_shouldStop && !_isDisposed)
            {
                if (_state == GameManagerState.UnhandledExceptionOccurred)
                {
                    throw new InvalidOperationException("Exception in the player logic has occurred.");
                }

                if (_state != GameManagerState.Running)
                {
                    Thread.Sleep(IdleTime);
                    continue;
                }

                lock (_syncLock)
                {
                    if (_shouldStop || _isDisposed)
                    {
                        continue;
                    }

                    var originalActiveBoard = GetActiveBoard();

                    var getMoveState = _getMoveStateContainer.Value;
                    if (getMoveState != null)
                    {
                        if (getMoveState.State != _state || getMoveState.ActiveBoard != originalActiveBoard)
                        {
                            getMoveState.Cancel();
                        }

                        Thread.Sleep(MoveWaitingIdleTime);
                        continue;
                    }

                    if (_state != GameManagerState.Running || _shouldStop || _isDisposed)
                    {
                        continue;
                    }

                    var state = new GetMoveState(_state, originalActiveBoard);
                    _getMoveStateContainer.Value = state;

                    var activeSide   = originalActiveBoard.ActiveSide;
                    var activePlayer = activeSide == GameSide.White ? White : Black;
                    var request      = new GetMoveRequest(originalActiveBoard, state.CancellationToken, _gameControl);
                    var task         = activePlayer.CreateGetMoveTask(request);

                    task.ContinueWith(
                        t =>
                    {
                        lock (_syncLock)
                        {
                            var moveState = _getMoveStateContainer.Value;
                            _getMoveStateContainer.Value = null;

                            if (moveState is null || moveState.IsCancelled.Value)
                            {
                                return;
                            }

                            var activeBoard = GetActiveBoard();

                            if (moveState.State != _state || moveState.ActiveBoard != activeBoard)
                            {
                                return;
                            }

                            var move         = t.Result.EnsureNotNull().FirstMove.EnsureNotNull();
                            var newGameBoard = activeBoard.MakeMove(move).EnsureNotNull();
                            _gameBoards.Push(newGameBoard);

                            AffectStates(GameManagerState.Paused);
                        }
                    },
                        TaskContinuationOptions.OnlyOnRanToCompletion);

                    task.ContinueWith(
                        t => _getMoveStateContainer.Value = null,
                        TaskContinuationOptions.OnlyOnCanceled);

                    task.ContinueWith(
                        t =>
                    {
                        _logger.Error(
                            $@"{Environment.NewLine}{Environment.NewLine}[{currentMethodName
                                    }] Unhandled exception has occurred: {t.Exception}{Environment.NewLine}{
                                    Environment.NewLine}");

                        lock (_syncLock)
                        {
                            _whiteTotalStopwatch.Stop();
                            _blackTotalStopwatch.Stop();
                            _whiteLastMoveStopwatch.Stop();
                            _blackLastMoveStopwatch.Stop();

                            _state = GameManagerState.UnhandledExceptionOccurred;
                        }
                    },
                        TaskContinuationOptions.OnlyOnFaulted);

                    Stopwatch totalStopwatch;
                    Stopwatch lastMoveStopwatch;
                    if (activeSide == GameSide.White)
                    {
                        totalStopwatch    = _whiteTotalStopwatch;
                        lastMoveStopwatch = _whiteLastMoveStopwatch;
                    }
                    else
                    {
                        totalStopwatch    = _blackTotalStopwatch;
                        lastMoveStopwatch = _blackLastMoveStopwatch;
                    }

                    totalStopwatch.Start();
                    lastMoveStopwatch.Restart();

                    RaisePlayerThinkingStartedAsync();
                    task.Start();
                }
            }
        }