Merge pull request #858 from ennorehling/develop

Develop
This commit is contained in:
Enno Rehling 2019-06-24 21:59:12 +02:00 committed by GitHub
commit c81d6e5f94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 25 deletions

View File

@ -1,5 +1,6 @@
#include <platform.h>
#include "kernel/config.h"
#include "kernel/faction.h"
#include "kernel/messages.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 *b = (const scholar *)rhs;
if (a->sk == b->sk) {
if (a->skill == b->skill) {
/* sort by level, descending: */
return b->level - a->level;
}
/* 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)
@ -42,12 +43,14 @@ int autostudy_init(scholar scholars[], int max_scholars, unit **units)
scholar * st = scholars + nscholars;
skill_t sk = getskill(u->faction->locale);
if (check_student(u, u->thisorder, sk)) {
st->sk = sk;
st->level = effskill_study(u, st->sk);
st->skill = (short)sk;
st->level = (short)effskill_study(u, sk);
st->learn = 0;
st->u = u;
if (++nscholars > max_scholars) {
log_fatal("you must increase MAXSCHOLARS");
if (++nscholars >= max_scholars) {
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;
while (ti != nscholars) {
skill_t sk = scholars[ti].sk;
int skill = scholars[ti].skill;
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;
ts += scholars[se].u->number; /* count total scholars */
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;
}
}
/* now si splits the teachers and students 1:10 */
/* 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) {
break;
}
tt += scholars[si].u->number;
}
/* 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 */
for (t = ti; t != se; ++t) {
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)
{
static int max_scholars;
unit *units = r->units;
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) {
int i, nscholars = autostudy_init(scholars, MAXSCHOLARS, &units);
int i, nscholars = autostudy_init(scholars, batchsize, &units);
if (nscholars > max_scholars) {
stats_count("automate.max_scholars", nscholars - max_scholars);
max_scholars = nscholars;
@ -177,7 +184,7 @@ void do_autostudy(region *r)
autostudy_run(scholars, nscholars);
for (i = 0; i != nscholars; ++i) {
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);
}
}
}

View File

@ -28,11 +28,12 @@ struct unit;
typedef struct scholar {
struct unit *u;
skill_t sk;
int level;
int learn;
short skill;
short level;
} scholar;
#define MAXSCHOLARS 128
#define STUDENTS_PER_TEACHER 10
void do_autostudy(struct region *r);

View File

@ -4,6 +4,7 @@
#include "automate.h"
#include "kernel/config.h"
#include "kernel/faction.h"
#include "kernel/order.h"
#include "kernel/region.h"
@ -46,22 +47,22 @@ static void test_autostudy_init(CuTest *tc) {
CuAssertPtrEquals(tc, u2, scholars[0].u);
CuAssertIntEquals(tc, 2, scholars[0].level);
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);
CuAssertIntEquals(tc, 0, scholars[1].level);
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);
CuAssertIntEquals(tc, 0, scholars[2].level);
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, u5, ulist);
CuAssertIntEquals(tc, 1, autostudy_init(scholars, 4, &ulist));
CuAssertPtrEquals(tc, u5, scholars[0].u);
CuAssertIntEquals(tc, 0, scholars[0].level);
CuAssertIntEquals(tc, 0, scholars[0].learn);
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[0].sk);
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[0].skill);
CuAssertPtrEquals(tc, NULL, ulist);
test_teardown();
}
@ -231,9 +232,44 @@ static void test_autostudy_run_skilldiff(CuTest *tc) {
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 *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_do_autostudy);
SUITE_ADD_TEST(suite, test_autostudy_init);
SUITE_ADD_TEST(suite, test_autostudy_run);
SUITE_ADD_TEST(suite, test_autostudy_run_noteachers);

View File

@ -300,7 +300,7 @@ unit *addplayer(region * r, faction * f)
} while (rc == NULL || urc == RC_DAEMON || !playerrace(rc));
u->irace = rc;
}
f->lastorders = 0;
f->lastorders = turn;
return u;
}

View File

@ -344,6 +344,7 @@ static void test_addplayer(CuTest *tc) {
CuAssertPtrNotNull(tc, u);
CuAssertPtrEquals(tc, r, u->region);
CuAssertPtrEquals(tc, f, u->faction);
CuAssertIntEquals(tc, turn, u->faction->lastorders);
CuAssertIntEquals(tc, i_get(u->items, itype), 10);
CuAssertPtrNotNull(tc, u->orders);
CuAssertIntEquals(tc, K_WORK, getkeyword(u->orders));

View File

@ -8,7 +8,7 @@
#ifndef ERESSEA_VERSION
/* 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
const char *eressea_version(void) {

View File

@ -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)
{
skill *sv = u->skills;