forked from github/server
commit
c81d6e5f94
7 changed files with 71 additions and 25 deletions
|
@ -1,5 +1,6 @@
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
|
|
||||||
|
#include "kernel/config.h"
|
||||||
#include "kernel/faction.h"
|
#include "kernel/faction.h"
|
||||||
#include "kernel/messages.h"
|
#include "kernel/messages.h"
|
||||||
#include "kernel/order.h"
|
#include "kernel/order.h"
|
||||||
|
@ -20,12 +21,12 @@ static int cmp_scholars(const void *lhs, const void *rhs)
|
||||||
{
|
{
|
||||||
const scholar *a = (const scholar *)lhs;
|
const scholar *a = (const scholar *)lhs;
|
||||||
const scholar *b = (const scholar *)rhs;
|
const scholar *b = (const scholar *)rhs;
|
||||||
if (a->sk == b->sk) {
|
if (a->skill == b->skill) {
|
||||||
/* sort by level, descending: */
|
/* sort by level, descending: */
|
||||||
return b->level - a->level;
|
return b->level - a->level;
|
||||||
}
|
}
|
||||||
/* order by skill */
|
/* order by skill */
|
||||||
return (int)a->sk - (int)b->sk;
|
return a->skill - b->skill;
|
||||||
}
|
}
|
||||||
|
|
||||||
int autostudy_init(scholar scholars[], int max_scholars, unit **units)
|
int autostudy_init(scholar scholars[], int max_scholars, unit **units)
|
||||||
|
@ -42,12 +43,14 @@ int autostudy_init(scholar scholars[], int max_scholars, unit **units)
|
||||||
scholar * st = scholars + nscholars;
|
scholar * st = scholars + nscholars;
|
||||||
skill_t sk = getskill(u->faction->locale);
|
skill_t sk = getskill(u->faction->locale);
|
||||||
if (check_student(u, u->thisorder, sk)) {
|
if (check_student(u, u->thisorder, sk)) {
|
||||||
st->sk = sk;
|
st->skill = (short)sk;
|
||||||
st->level = effskill_study(u, st->sk);
|
st->level = (short)effskill_study(u, sk);
|
||||||
st->learn = 0;
|
st->learn = 0;
|
||||||
st->u = u;
|
st->u = u;
|
||||||
if (++nscholars > max_scholars) {
|
if (++nscholars >= max_scholars) {
|
||||||
log_fatal("you must increase MAXSCHOLARS");
|
log_warning("you must increase MAXSCHOLARS");
|
||||||
|
*units = u->next;
|
||||||
|
return max_scholars;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,26 +84,26 @@ void autostudy_run(scholar scholars[], int nscholars)
|
||||||
{
|
{
|
||||||
int ti = 0;
|
int ti = 0;
|
||||||
while (ti != nscholars) {
|
while (ti != nscholars) {
|
||||||
skill_t sk = scholars[ti].sk;
|
int skill = scholars[ti].skill;
|
||||||
int t, se, ts = 0, tt = 0, si = ti;
|
int t, se, ts = 0, tt = 0, si = ti;
|
||||||
for (se = ti; se != nscholars && scholars[se].sk == sk; ++se) {
|
for (se = ti; se != nscholars && scholars[se].skill == skill; ++se) {
|
||||||
int mint;
|
int mint;
|
||||||
ts += scholars[se].u->number; /* count total scholars */
|
ts += scholars[se].u->number; /* count total scholars */
|
||||||
mint = (ts + 10) / 11; /* need a minimum of ceil(ts/11) teachers */
|
mint = (ts + 10) / 11; /* need a minimum of ceil(ts/11) teachers */
|
||||||
for (; mint > tt && si != nscholars && scholars[si].sk == sk; ++si) {
|
for (; mint > tt && si != nscholars && scholars[si].skill == skill; ++si) {
|
||||||
tt += scholars[si].u->number;
|
tt += scholars[si].u->number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* now si splits the teachers and students 1:10 */
|
/* now si splits the teachers and students 1:10 */
|
||||||
/* first student must be 2 levels below first teacher: */
|
/* first student must be 2 levels below first teacher: */
|
||||||
for (; si != se && scholars[si].sk == sk; ++si) {
|
for (; si != se && scholars[si].skill == skill; ++si) {
|
||||||
if (scholars[si].level + TEACHDIFFERENCE <= scholars[ti].level) {
|
if (scholars[si].level + TEACHDIFFERENCE <= scholars[ti].level) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tt += scholars[si].u->number;
|
tt += scholars[si].u->number;
|
||||||
}
|
}
|
||||||
/* now si is the first unit we can teach, if we can teach any */
|
/* now si is the first unit we can teach, if we can teach any */
|
||||||
if (si == se || scholars[si].sk != sk) {
|
if (si == se || scholars[si].skill != skill) {
|
||||||
/* there are no students, so standard learning for everyone */
|
/* there are no students, so standard learning for everyone */
|
||||||
for (t = ti; t != se; ++t) {
|
for (t = ti; t != se; ++t) {
|
||||||
learning(scholars + t, scholars[t].u->number);
|
learning(scholars + t, scholars[t].u->number);
|
||||||
|
@ -161,15 +164,19 @@ void autostudy_run(scholar scholars[], int nscholars)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAXSCHOLARS 512
|
|
||||||
|
|
||||||
void do_autostudy(region *r)
|
void do_autostudy(region *r)
|
||||||
{
|
{
|
||||||
static int max_scholars;
|
static int max_scholars;
|
||||||
unit *units = r->units;
|
unit *units = r->units;
|
||||||
scholar scholars[MAXSCHOLARS];
|
scholar scholars[MAXSCHOLARS];
|
||||||
|
static int config;
|
||||||
|
static int batchsize = MAXSCHOLARS;
|
||||||
|
if (config_changed(&config)) {
|
||||||
|
batchsize = config_get_int("automate.batchsize", MAXSCHOLARS);
|
||||||
|
assert(batchsize <= MAXSCHOLARS);
|
||||||
|
}
|
||||||
while (units) {
|
while (units) {
|
||||||
int i, nscholars = autostudy_init(scholars, MAXSCHOLARS, &units);
|
int i, nscholars = autostudy_init(scholars, batchsize, &units);
|
||||||
if (nscholars > max_scholars) {
|
if (nscholars > max_scholars) {
|
||||||
stats_count("automate.max_scholars", nscholars - max_scholars);
|
stats_count("automate.max_scholars", nscholars - max_scholars);
|
||||||
max_scholars = nscholars;
|
max_scholars = nscholars;
|
||||||
|
@ -177,7 +184,7 @@ void do_autostudy(region *r)
|
||||||
autostudy_run(scholars, nscholars);
|
autostudy_run(scholars, nscholars);
|
||||||
for (i = 0; i != nscholars; ++i) {
|
for (i = 0; i != nscholars; ++i) {
|
||||||
int days = STUDYDAYS * scholars[i].learn;
|
int days = STUDYDAYS * scholars[i].learn;
|
||||||
learn_skill(scholars[i].u, scholars[i].sk, days);
|
learn_skill(scholars[i].u, (skill_t)scholars[i].skill, days);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,12 @@ struct unit;
|
||||||
|
|
||||||
typedef struct scholar {
|
typedef struct scholar {
|
||||||
struct unit *u;
|
struct unit *u;
|
||||||
skill_t sk;
|
|
||||||
int level;
|
|
||||||
int learn;
|
int learn;
|
||||||
|
short skill;
|
||||||
|
short level;
|
||||||
} scholar;
|
} scholar;
|
||||||
|
|
||||||
|
#define MAXSCHOLARS 128
|
||||||
#define STUDENTS_PER_TEACHER 10
|
#define STUDENTS_PER_TEACHER 10
|
||||||
|
|
||||||
void do_autostudy(struct region *r);
|
void do_autostudy(struct region *r);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "automate.h"
|
#include "automate.h"
|
||||||
|
|
||||||
|
#include "kernel/config.h"
|
||||||
#include "kernel/faction.h"
|
#include "kernel/faction.h"
|
||||||
#include "kernel/order.h"
|
#include "kernel/order.h"
|
||||||
#include "kernel/region.h"
|
#include "kernel/region.h"
|
||||||
|
@ -46,22 +47,22 @@ static void test_autostudy_init(CuTest *tc) {
|
||||||
CuAssertPtrEquals(tc, u2, scholars[0].u);
|
CuAssertPtrEquals(tc, u2, scholars[0].u);
|
||||||
CuAssertIntEquals(tc, 2, scholars[0].level);
|
CuAssertIntEquals(tc, 2, scholars[0].level);
|
||||||
CuAssertIntEquals(tc, 0, scholars[0].learn);
|
CuAssertIntEquals(tc, 0, scholars[0].learn);
|
||||||
CuAssertIntEquals(tc, SK_ENTERTAINMENT, scholars[0].sk);
|
CuAssertIntEquals(tc, SK_ENTERTAINMENT, scholars[0].skill);
|
||||||
CuAssertPtrEquals(tc, u1, scholars[1].u);
|
CuAssertPtrEquals(tc, u1, scholars[1].u);
|
||||||
CuAssertIntEquals(tc, 0, scholars[1].level);
|
CuAssertIntEquals(tc, 0, scholars[1].level);
|
||||||
CuAssertIntEquals(tc, 0, scholars[1].learn);
|
CuAssertIntEquals(tc, 0, scholars[1].learn);
|
||||||
CuAssertIntEquals(tc, SK_ENTERTAINMENT, scholars[1].sk);
|
CuAssertIntEquals(tc, SK_ENTERTAINMENT, scholars[1].skill);
|
||||||
CuAssertPtrEquals(tc, u3, scholars[2].u);
|
CuAssertPtrEquals(tc, u3, scholars[2].u);
|
||||||
CuAssertIntEquals(tc, 0, scholars[2].level);
|
CuAssertIntEquals(tc, 0, scholars[2].level);
|
||||||
CuAssertIntEquals(tc, 0, scholars[2].learn);
|
CuAssertIntEquals(tc, 0, scholars[2].learn);
|
||||||
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[2].sk);
|
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[2].skill);
|
||||||
CuAssertPtrEquals(tc, NULL, scholars[3].u);
|
CuAssertPtrEquals(tc, NULL, scholars[3].u);
|
||||||
CuAssertPtrEquals(tc, u5, ulist);
|
CuAssertPtrEquals(tc, u5, ulist);
|
||||||
CuAssertIntEquals(tc, 1, autostudy_init(scholars, 4, &ulist));
|
CuAssertIntEquals(tc, 1, autostudy_init(scholars, 4, &ulist));
|
||||||
CuAssertPtrEquals(tc, u5, scholars[0].u);
|
CuAssertPtrEquals(tc, u5, scholars[0].u);
|
||||||
CuAssertIntEquals(tc, 0, scholars[0].level);
|
CuAssertIntEquals(tc, 0, scholars[0].level);
|
||||||
CuAssertIntEquals(tc, 0, scholars[0].learn);
|
CuAssertIntEquals(tc, 0, scholars[0].learn);
|
||||||
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[0].sk);
|
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[0].skill);
|
||||||
CuAssertPtrEquals(tc, NULL, ulist);
|
CuAssertPtrEquals(tc, NULL, ulist);
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
@ -231,9 +232,44 @@ static void test_autostudy_run_skilldiff(CuTest *tc) {
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_do_autostudy(CuTest *tc) {
|
||||||
|
scholar scholars[2];
|
||||||
|
int nscholars;
|
||||||
|
unit *u1, *u2, *u3, *ulist;
|
||||||
|
faction *f;
|
||||||
|
region *r;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
r = test_create_plain(0, 0);
|
||||||
|
f = test_create_faction(NULL);
|
||||||
|
u1 = test_create_unit(f, r);
|
||||||
|
u1->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
|
set_number(u1, 1);
|
||||||
|
set_level(u1, SK_PERCEPTION, 2);
|
||||||
|
u2 = test_create_unit(f, r);
|
||||||
|
u2->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
|
set_number(u2, 10);
|
||||||
|
u3 = test_create_unit(f, r);
|
||||||
|
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
|
set_number(u3, 10);
|
||||||
|
scholars[1].u = NULL;
|
||||||
|
ulist = r->units;
|
||||||
|
config_set("automate.batchsize", "2");
|
||||||
|
CuAssertIntEquals(tc, 2, nscholars = autostudy_init(scholars, 2, &ulist));
|
||||||
|
CuAssertPtrEquals(tc, u3, ulist);
|
||||||
|
autostudy_run(scholars, nscholars);
|
||||||
|
CuAssertIntEquals(tc, 0, scholars[0].learn);
|
||||||
|
CuAssertIntEquals(tc, 20, scholars[1].learn);
|
||||||
|
CuAssertIntEquals(tc, 1, nscholars = autostudy_init(scholars, 2, &ulist));
|
||||||
|
autostudy_run(scholars, nscholars);
|
||||||
|
CuAssertIntEquals(tc, 10, scholars[0].learn);
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_automate_suite(void)
|
CuSuite *get_automate_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_do_autostudy);
|
||||||
SUITE_ADD_TEST(suite, test_autostudy_init);
|
SUITE_ADD_TEST(suite, test_autostudy_init);
|
||||||
SUITE_ADD_TEST(suite, test_autostudy_run);
|
SUITE_ADD_TEST(suite, test_autostudy_run);
|
||||||
SUITE_ADD_TEST(suite, test_autostudy_run_noteachers);
|
SUITE_ADD_TEST(suite, test_autostudy_run_noteachers);
|
||||||
|
|
|
@ -300,7 +300,7 @@ unit *addplayer(region * r, faction * f)
|
||||||
} while (rc == NULL || urc == RC_DAEMON || !playerrace(rc));
|
} while (rc == NULL || urc == RC_DAEMON || !playerrace(rc));
|
||||||
u->irace = rc;
|
u->irace = rc;
|
||||||
}
|
}
|
||||||
f->lastorders = 0;
|
f->lastorders = turn;
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -344,6 +344,7 @@ static void test_addplayer(CuTest *tc) {
|
||||||
CuAssertPtrNotNull(tc, u);
|
CuAssertPtrNotNull(tc, u);
|
||||||
CuAssertPtrEquals(tc, r, u->region);
|
CuAssertPtrEquals(tc, r, u->region);
|
||||||
CuAssertPtrEquals(tc, f, u->faction);
|
CuAssertPtrEquals(tc, f, u->faction);
|
||||||
|
CuAssertIntEquals(tc, turn, u->faction->lastorders);
|
||||||
CuAssertIntEquals(tc, i_get(u->items, itype), 10);
|
CuAssertIntEquals(tc, i_get(u->items, itype), 10);
|
||||||
CuAssertPtrNotNull(tc, u->orders);
|
CuAssertPtrNotNull(tc, u->orders);
|
||||||
CuAssertIntEquals(tc, K_WORK, getkeyword(u->orders));
|
CuAssertIntEquals(tc, K_WORK, getkeyword(u->orders));
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#ifndef ERESSEA_VERSION
|
#ifndef ERESSEA_VERSION
|
||||||
/* the version number, if it was not passed to make with -D */
|
/* the version number, if it was not passed to make with -D */
|
||||||
#define ERESSEA_VERSION "3.20.0"
|
#define ERESSEA_VERSION "3.21.0"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char *eressea_version(void) {
|
const char *eressea_version(void) {
|
||||||
|
|
|
@ -860,8 +860,9 @@ void reduce_skill_days(unit *u, skill_t sk, int days) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Talente von Daemonen verschieben sich.
|
/**
|
||||||
*/
|
* Talente von Daemonen verschieben sich.
|
||||||
|
*/
|
||||||
void demon_skillchange(unit *u)
|
void demon_skillchange(unit *u)
|
||||||
{
|
{
|
||||||
skill *sv = u->skills;
|
skill *sv = u->skills;
|
||||||
|
|
Loading…
Reference in a new issue