public void IsStalemate_ShouldReturnTrue_WhenKingHasNoMovesAndNotInCheck(string fen) { var boardState = _fenParser.ParseFen(fen); var result = _moveValidator.IsStalemate(boardState); result.Should().BeTrue(); }
public async Task Move(string moveNotation, string gameId) { _logger.LogInformation("Move {Move} sent in game {GameId}", moveNotation, gameId); await Clients.Caller.SendAsync(GameHubOutgoingMessages.MOVE_RECEIVED); var game = _gameRepository.GetGameById(gameId); if (game == null) { return; } if (!game.Active) { _logger.LogInformation("Move {Move} was illegal in game {GameId} because game is inactive", moveNotation, gameId); await Clients.Caller.SendAsync(GameHubOutgoingMessages.ILLEGAL_MOVE, game.Fen); return; } var userIdString = Context.UserIdentifier; if (userIdString == null) { _logger.LogInformation("Move {Move} was illegal in game {GameId} because user was not logged in", moveNotation, gameId); await Clients.Caller.SendAsync(GameHubOutgoingMessages.ILLEGAL_MOVE, game.Fen); return; } var parsedUserId = int.Parse(userIdString); if (parsedUserId != game.WhitePlayerId && parsedUserId != game.BlackPlayerId) { _logger.LogInformation("Move {Move} was illegal in game {GameId} because user {userId} is not a player", moveNotation, gameId, parsedUserId); await Clients.Caller.SendAsync(GameHubOutgoingMessages.ILLEGAL_MOVE, game.Fen); return; } var moveValidationResult = _moveValidator.ValidateMove(game.Fen, moveNotation); if (!moveValidationResult.IsValid) { _logger.LogInformation("Move {Move} was illegal in game {GameId}", moveNotation, gameId); await Clients.Caller.SendAsync(GameHubOutgoingMessages.ILLEGAL_MOVE, game.Fen); return; } var move = _coordinateNotationParser.ParseNotationMove(moveNotation); var currentBoardState = _fenParser.ParseFen(game.Fen); var newBoardState = _moveHandler.ApplyMove(currentBoardState, move, moveValidationResult); _gameRepository.AddMoveToGame(gameId, moveNotation, newBoardState.Fen); await Clients.Group($"{GAME_GROUP_PREFIX}{gameId}") .SendAsync(GameHubOutgoingMessages.MOVE_PLAYED, moveNotation); if (moveValidationResult.ShouldResetHalfmoveClock) { _gameRepository.ClearPositionsFromIrreversibleMove(gameId); } _gameRepository.AddPositionToGame(gameId, newBoardState.Fen); var positionsSinceIrreversibleMove = _gameRepository.GetPositionsSinceIrreversibleMove(gameId); if (_moveValidator.IsCheckmate(newBoardState)) { var winner = currentBoardState.ActiveColor; await EndGame(game, winner, GameConstants.CHECKMATE_TERMINATION, GameHubOutgoingMessages.CHECKMATE); } else if (_moveValidator.IsStalemate(newBoardState)) { await EndGame(game, null, GameConstants.STALEMATE_TERMINATION, GameHubOutgoingMessages.DRAW); } else if (newBoardState.HalfmoveClock >= 100) { await EndGame(game, null, GameConstants.FIFTY_MOVE_RULE_TERMINATION, GameHubOutgoingMessages.DRAW); } else if (_moveValidator.IsThreefoldRepetition(newBoardState, positionsSinceIrreversibleMove)) { await EndGame(game, null, GameConstants.THREEFOLD_REPETITION_TERMINATION, GameHubOutgoingMessages.DRAW); } }