Weird dice roll mechanic There's a game called Cthulhutech which has a dice-based problem resolution system.
I'll use a notation of nd+b where relevant, where "n" is the number of 10-sided dice (giving a value from 1 to 10), and b is the skill bonus.
The first part is simple: The result of a roll is (initially), the highest of all dice.
The next complication is that if any number appears multiple times, the result is the sum of all copies: i.e, if I roll 3d+0 getting [5,5,9], the result is 10 (5+5).
The final complexity is that rolling a series of (at least 3) contiguous numbers results in the sum of all of them: i.e., rolling 5d+0 getting [2,4,5,6,10] is 15 (4+5+6).
The final result is the highest of all three possibilities, so 2d+0 => [2,2,10] is 10.
So, multiple related questions:


*

*Is it possible to find a probability function for this (That would be f(n,b,t) represents P(nd+b>=t) where n is the number of dice, b is the bonus, and t is the target. (Or, equivalently, p(nd>=t-b))).

*Since I can pay a certain amount of skill points in order to raise either n or b, is it valid to take df/dt vs df/db to decide which option is better?

 A: (1) Yes, why wouldn't it be possible? Here is an implementation in Python. Beware that the algorithm for computing the outcomes table for each $n$ is $O(10^n)$, and it already takes over a minute to run on my machine with $n = 7$.
from itertools import product, tee
from collections import Counter

min_seq_len = 3
sides = 10

def outcomes(n_dice):
    counts = Counter()
    for got in product(*tee(range(1, sides + 1), n_dice)):
        # First check for n-of-a-kind (including 1-of-a-kind).
        best = max(n*v for n, v in Counter(got).items())
        # Now look for sequences.
        seq = []
        for v in sorted(set(got)):
            if not seq or v == seq[-1] + 1:
                seq.append(v)
            else:
                if len(seq) >= min_seq_len:
                    best = max(best, sum(seq))
                del seq[:]
        if len(seq) >= min_seq_len:
            best = max(best, sum(seq))
        counts[best] += 1
    return counts

def p_at_least(n_dice, bonus, the_min):
    enough = 0
    total = 0
    for n, outcome in outcomes(n_dice).items():
        total += n
        if outcome + bonus >= the_min:
            enough += n
    return enough/total

print(p_at_least(7, 2, 5))

(2) It seems that your concern is whether $f(n, b + 1, t)$ or $f(n + 1, b, t)$ is bigger for a given $n$, $b$, and $t$, which a derivative won't tell you.
A: Results for 1-10 dice

Tabular form (Google Sheets).
CthulhuTech was also asked about on rpg.se.
How much flat bonus is a die worth?

Since I can pay a certain amount of skill points in order to raise either n or b, is it valid to take df/dt vs df/db to decide which option is better?

Everything here is discrete, so you can only really take a difference as Kodiologist  said. Even then you would have to decide what sorts of target numbers you want to optimize for. Looking at the graph:

*

*Flat bonuses help you do easy things reliably.

*Extra dice give you a better chance at doing hard things.

Of course, the cost ratio between the two will come into play as well. For a simple rule of thumb I would say 1 die is comparable to a +2 flat bonus.
Algorithm details
It is possible to compute the result in polynomial time by phrasing the mechanic as a state transition function with the inputs being how many dice rolled 1, how many rolled 2, and so forth. Even for 10 dice it takes longer to graph the result than to compute it.
def next_state(self, state, outcome, count):
    score, run, prev_outcome = state or (0, 0, outcome - 1)
    if count > 0:
        set_score = outcome * count
        run_score = 0
        if outcome == prev_outcome + 1:
            run += 1
        else:
            run = 1
        if run >= 3:
            # This could be the triangular formula, but it's clearer this way.
            for i in range(run): run_score += (outcome - i)
        score = max(set_score, run_score, score)
    else:
        # No dice rolled this number, so the score remains the same.
        run = 0
    return score, run, outcome

Here's a JupyterLite notebook that you can run in your browser. The underlying general-purpose algorithm is described here though I'm still working on a better explanation. I've implemented it in my Icepool Python package.
