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);
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(); } } }