diff --git a/conf/e4/config.json b/conf/e4/config.json index a32d7aab7..894f6e3f9 100644 --- a/conf/e4/config.json +++ b/conf/e4/config.json @@ -29,6 +29,7 @@ "recruit.allow_merge": true, "study.expensivemigrants": true, "study.speedup": 2, + "study.from_use": 2, "world.era": 3, "rules.migrants.max": 0, "rules.reserve.twophase": true, diff --git a/src/kernel/config.c b/src/kernel/config.c index f31083130..dbc2d5c10 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1599,16 +1599,6 @@ int maintenance_cost(const struct unit *u) return u_race(u)->maintenance * u->number; } -int produceexp(struct unit *u, skill_t sk, int n) -{ - if (global.producexpchance > 0.0F) { - if (n == 0 || !playerrace(u_race(u))) - return 0; - learn_skill(u, sk, global.producexpchance); - } - return 0; -} - int lovar(double xpct_x2) { int n = (int)(xpct_x2 * 500) + 1; diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 95608e709..df97d2f41 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1933,3 +1933,22 @@ bool unit_name_equals_race(const unit *u) { bool unit_can_study(const unit *u) { return !((u_race(u)->flags & RCF_NOLEARN) || fval(u, UFL_WERE)); } + +static double produceexp_chance(void) { + return global.producexpchance; +} + +void produceexp_ex(struct unit *u, skill_t sk, int n, void(*learn)(unit *, skill_t, double)) +{ + if (n != 0 && playerrace(u_race(u))) { + double chance = produceexp_chance(); + if (chance > 0.0F) { + learn(u, sk, (n * chance) / u->number); + } + } +} + +void produceexp(struct unit *u, skill_t sk, int n) +{ + produceexp_ex(u, sk, n, learn_skill); +} diff --git a/src/kernel/unit.h b/src/kernel/unit.h index dcb7ad6e3..7a2f3e80f 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -161,8 +161,9 @@ extern "C" { struct skill *unit_skill(const struct unit *u, skill_t id); bool has_skill(const unit * u, skill_t sk); int effskill(const struct unit *u, skill_t sk, const struct region *r); - int produceexp(struct unit *u, skill_t sk, int n); int SkillCap(skill_t sk); + void produceexp(struct unit *u, skill_t sk, int n); + void produceexp_ex(struct unit *u, skill_t sk, int n, void(*learn)(unit *, skill_t, double)); void set_level(struct unit *u, skill_t id, int level); int get_level(const struct unit *u, skill_t id); diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 8dffbca3f..7106db7c2 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -350,6 +350,30 @@ static void test_age_familiar(CuTest *tc) { test_cleanup(); } +static CuTest *g_tc; + +static void cb_learn_one(unit *u, skill_t sk, double chance) { + CuAssertIntEquals(g_tc, SK_ALCHEMY, sk); + CuAssertDblEquals(g_tc, global.producexpchance / u->number, chance, 0.01); +} + +static void cb_learn_two(unit *u, skill_t sk, double chance) { + CuAssertIntEquals(g_tc, SK_ALCHEMY, sk); + CuAssertDblEquals(g_tc, 2 * global.producexpchance / u->number, chance, 0.01); +} + +static void test_produceexp(CuTest *tc) { + unit *u; + + g_tc = tc; + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + global.producexpchance = 1.0; + produceexp_ex(u, SK_ALCHEMY, 1, cb_learn_one); + produceexp_ex(u, SK_ALCHEMY, 2, cb_learn_two); + test_cleanup(); +} + CuSuite *get_unit_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -368,5 +392,6 @@ CuSuite *get_unit_suite(void) SUITE_ADD_TEST(suite, test_skill_hunger); SUITE_ADD_TEST(suite, test_skill_familiar); SUITE_ADD_TEST(suite, test_age_familiar); + SUITE_ADD_TEST(suite, test_produceexp); return suite; }