Как создать регулируемую формулу для повышения уровня RPG?

Я пытаюсь создать формулу, которая может быть изменена просто путем изменения двух значений: number_of_levels и last_level_experience. Это позволяет людям изменять игру, чтобы изменить требования к выравниванию.

У меня есть так, что я могу указать количество XP, необходимое для последнего уровня, но я хочу иметь возможность контролировать XP, необходимый для первого уровня, который в этом случае может сильно отличаться. Например, если у меня есть 40 уровней и 1 000 000 XP для последнего уровня, то требование первого уровня - это 625. Но если я изменю уровни до 80, первый уровень будет равен 156. В обоих случаях нужен последний уровень 1000000.

Должен быть какой-то способ заставить компьютер выработать подходящую кривую, учитывая только эти два основных значения.

#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;
    }
}

Вывод:

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)
43 голоса | спросил Truncheon 12 MonEurope/Moscow2011-12-12T11:07:50+04:00Europe/Moscow12bEurope/MoscowMon, 12 Dec 2011 11:07:50 +0400 2011, 11:07:50

2 ответа


68

Хотя существует множество способов выбора, обычно для выравнивания кривых следует правило power , например следующее:

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

Основное преимущество этой формулы можно легко объяснить: для данного правила существует фиксированное значение N такое, что каждый уровень стоит на N процентов больше, чем предыдущий .

Ваши начальные переменные добавляют следующие ограничения:

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

Два уравнения, два неизвестных. Это выглядит хорошо. Простая математика дает A и B:

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

Результат в следующем коде:

#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;
    }
}

И следующий вывод:

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
ответил sam hocevar 12 MonEurope/Moscow2011-12-12T15:18:27+04:00Europe/Moscow12bEurope/MoscowMon, 12 Dec 2011 15:18:27 +0400 2011, 15:18:27
16

Не забывайте округлять цифры после того, как вы вычислили свою кривую. Не имеет смысла рассказывать игроку, что ему нужно 119 378 очков опыта, чтобы достичь следующего уровня - потому что человек всегда будет понимать его как «примерно 120 000». Таким образом, вам будет лучше делать закругление самостоятельно и представлять «чистые» результаты своим игрокам. Например, следующий код (который распространяется на Сэма Хосевара) будет пытаться округлить до 2,2 значащих цифр (очевидно, что константа может быть изменена по вашему желанию):

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)) )

Вывод:

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
ответил Pasha 14 Mayam13 2013, 10:02:43

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132