Come creare una formula regolabile per i requisiti di aumento del livello dei giochi di ruolo?


43

Sto cercando di creare una formula che può essere modificata semplicemente cambiando due valori: number_of_levels e last_level_experience. Questo per consentire alle persone che modificano il gioco di cambiare i requisiti di livellamento.

Ho capito che posso specificare il numero di XP necessari per l'ultimo livello, ma voglio essere in grado di controllare gli XP necessari per il primo livello, che in questo caso possono differire notevolmente. Ad esempio, se ho 40 livelli e 1.000.000 di XP per l'ultimo livello, il requisito per il primo livello è quindi 625. Ma se cambio i livelli in 80, il primo livello diventa 156. In entrambi i casi, l'ultimo livello deve 1.000.000.

Ci deve essere un modo per far sì che il computer elabori una curva adatta dati solo questi due valori di base.

#include <iostream>

int main()
{
    int levels = 40;
    if (levels < 2) levels = 2;

    int experience_for_last_level = 1e6;
    float fraction = 1.0 / levels;

    {
        int i = 0;
        float fraction_counter = fraction;
        int counter = levels;
        int total = 0;

        for (i = 1; i <= levels; ++i, fraction_counter += fraction, --counter)
        {
            int a = static_cast<int>(fraction_counter * experience_for_last_level / counter);

            std::cout <<"Level "<<i<<":  "<<a<<" ("<<counter<<")"<<"\n";

            total += a;
        }

        std::cout << "\nTotal Exp: " << total;
    }
}

Produzione:

Level 1:  625   (40)      Level 15: 14423  (26)      Level 29: 60416  (12)
Level 2:  1282  (39)      Level 16: 16000  (25)      Level 30: 68181  (11)
Level 3:  1973  (38)      Level 17: 17708  (24)      Level 31: 77499  (10)
Level 4:  2702  (37)      Level 18: 19565  (23)      Level 32: 88888  (9)
Level 5:  3472  (36)      Level 19: 21590  (22)      Level 33: 103124 (8)
Level 6:  4285  (35)      Level 20: 23809  (21)      Level 34: 121428 (7)
Level 7:  5147  (34)      Level 21: 26250  (20)      Level 35: 145833 (6)
Level 8:  6060  (33)      Level 22: 28947  (19)      Level 36: 179999 (5)
Level 9:  7031  (32)      Level 23: 31944  (18)      Level 37: 231249 (4)
Level 10: 8064  (31)      Level 24: 35294  (17)      Level 38: 316666 (3)
Level 11: 9166  (30)      Level 25: 39062  (16)      Level 39: 487499 (2)
Level 12: 10344 (29)      Level 26: 43333  (15)      Level 40: 999999 (1)
Level 13: 11607 (28)      Level 27: 48214  (14)
Level 14: 12962 (27)      Level 28: 53846  (13)

13
Il problema fondamentale è che ci sono infinite curve di livello XP che terminerebbero con l'ultimo livello che richiede così tanto XP. Non hai limitato le dimensioni del problema, perché non hai dichiarato come desideri che XP cambi da livello a livello. Vuoi una curva di crescita esponenziale? Una curva di crescita parabolica? Lineare? Il tuo problema è irrisolvibile nel suo stato attuale. Personalmente, se stessi modificando il gioco, vorrei un maggiore controllo sulla curva XP rispetto all'ultimo livello e all'ultimo livello XP. Vorrei controllare l'attuale curva stessa.
Nicol Bolas,

Posso consentire ai modder di controllare il livellamento tramite uno script.
Truncheon,

Risposte:


70

Sebbene ci siano infiniti modi per sceglierli, è comune che le curve di livellamento seguano una regola di potere come la seguente:

f(level) == A * exp(B * level)

Il vantaggio principale di questa formula può essere facilmente spiegato: per una data regola, esiste un valore fisso N tale che ogni livello costa N percento in più rispetto alla precedente .

Le variabili iniziali aggiungono le seguenti restrizioni:

f(1) - f(0) == experience_for_first_level
f(levels) - f(levels - 1) == experience_for_last_level

Due equazioni, due incognite. Questo sembra buono. La matematica semplice dà Ae B:

B = log(experience_for_last_level / experience_for_first_level) / (levels - 1);
A = experience_for_first_level / (exp(B) - 1);

Risultato nel seguente codice:

#include <cmath>
#include <iostream>

int main(void)
{
    int levels = 40;
    int xp_for_first_level = 1000;
    int xp_for_last_level = 1000000;

    double B = log((double)xp_for_last_level / xp_for_first_level) / (levels - 1);
    double A = (double)xp_for_first_level / (exp(B) - 1.0);

    for (int i = 1; i <= levels; i++)
    {
        int old_xp = round(A * exp(B * (i - 1)));
        int new_xp = round(A * exp(B * i));
        std::cout << i << " " << (new_xp - old_xp) << std::endl;
    }
}

E il seguente output:

1 1000          9 4125          17 17012        25 70170        33 289427
2 1193          10 4924         18 20309        26 83768        34 345511
3 1425          11 5878         19 24245        27 100000       35 412462
4 1702          12 7017         20 28943        28 119378       36 492389
5 2031          13 8377         21 34551        29 142510       37 587801
6 2424          14 10000        22 41246        30 170125       38 701704
7 2894          15 11938        23 49239        31 203092       39 837678
8 3455          16 14251        24 58780        32 242446       40 1000000

12
Se solo tutte le risposte fossero state così ben pianificate e pensate.
Nate,

La curva qui è molto più appetibile.
Truncheon,

Buona risposta. Questa potrebbe essere una domanda stupida, ma come calcoli Nche hai descritto sopra? E se volessi rendere Nla variabile collegabile? Fammi sapere se dovrei fare una domanda separata per questo.
Daniel Kaplan,

1
@tieTYT la relazione tra Ne Bè exp(B) = 1 + N, o B = log(1 + N). Quindi, se si desidera che ogni livello richieda ad esempio il 15% in più rispetto al precedente, è necessario B = log(1 + 0.15) = 0.13976.
sam hocevar,

17

Non dimenticare di arrotondare i numeri dopo aver capito la curva. Non ha molto senso dire al giocatore che ha bisogno di 119.378 punti esperienza per raggiungere il livello successivo, perché la persona lo capirà sempre come "circa 120.000". Quindi starai meglio facendo il round te stesso e presentando risultati "puliti" ai tuoi giocatori. Ad esempio il seguente codice (che si estende su quello di Sam Hocevar) tenterà di arrotondare a .22.2 cifre significative (ovviamente quella costante può essere ottimizzata come si desidera):

from math import exp, log

levels = 40
xp_for_first_level = 1000
xp_for_last_level = 1000000

B = log(1.0 * xp_for_last_level / xp_for_first_level) / (levels - 1)
A = 1.0 * xp_for_first_level / (exp(B) - 1.0)

def xp_for_level(i):
    x = int(A * exp(B * i))
    y = 10**int(log(x) / log(10) - 2.2)
    return int(x / y) * y

for i in range(1, levels+1):
    print( "%d:  %d" % (i, xp_for_level(i) - xp_for_level(i-1)) )

L'output è:

1:  1000     9:  4200     17:  17100    25:  70000     33:  287000
2:  1190    10:  4900     18:  20300    26:  84000     34:  340000
3:  1420    11:  5900     19:  24200    27:  100000    35:  420000
4:  1710    12:  7000     20:  28700    28:  119000    36:  490000
5:  2030    13:  8400     21:  34000    29:  142000    37:  590000
6:  2420    14:  10000    22:  42000    30:  171000    38:  700000
7:  2870    15:  11900    23:  49000    31:  203000    39:  840000
8:  3400    16:  14200    24:  59000    32:  242000    40:  1000000
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.