forked from github/server
commit
34abedd642
24 changed files with 491 additions and 88 deletions
2
clibs
2
clibs
|
@ -1 +1 @@
|
||||||
Subproject commit d86c8525489d7f11b7ba13e101bb59ecf160b871
|
Subproject commit 66a891b383f1a51bb0d4e5cf002530f7f70bf7f4
|
BIN
src/.DS_Store
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
Binary file not shown.
|
@ -86,6 +86,7 @@ ENDIF()
|
||||||
|
|
||||||
set (ERESSEA_SRC
|
set (ERESSEA_SRC
|
||||||
vortex.c
|
vortex.c
|
||||||
|
automate.c
|
||||||
move.c
|
move.c
|
||||||
piracy.c
|
piracy.c
|
||||||
spells.c
|
spells.c
|
||||||
|
@ -187,6 +188,7 @@ set(TESTS_SRC
|
||||||
tests.c
|
tests.c
|
||||||
academy.test.c
|
academy.test.c
|
||||||
alchemy.test.c
|
alchemy.test.c
|
||||||
|
automate.test.c
|
||||||
battle.test.c
|
battle.test.c
|
||||||
creport.test.c
|
creport.test.c
|
||||||
direction.test.c
|
direction.test.c
|
||||||
|
|
|
@ -33,13 +33,13 @@ void academy_teaching_bonus(struct unit *u, skill_t sk, int students) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool academy_can_teach(unit *teacher, unit *student, skill_t sk) {
|
bool academy_can_teach(unit *teacher, unit *scholar, skill_t sk) {
|
||||||
const struct building_type *btype = bt_find("academy");
|
const struct building_type *btype = bt_find("academy");
|
||||||
if (active_building(teacher, btype) && active_building(student, btype)) {
|
if (active_building(teacher, btype) && active_building(scholar, btype)) {
|
||||||
int j = study_cost(student, sk) * 2;
|
int j = study_cost(scholar, sk) * 2;
|
||||||
if (j < 50) j = 50;
|
if (j < 50) j = 50;
|
||||||
/* kann Einheit das zahlen? */
|
/* kann Einheit das zahlen? */
|
||||||
return get_pooled(student, get_resourcetype(R_SILVER), GET_DEFAULT, j) >= j;
|
return get_pooled(scholar, get_resourcetype(R_SILVER), GET_DEFAULT, j) >= j;
|
||||||
/* sonst nehmen sie nicht am Unterricht teil */
|
/* sonst nehmen sie nicht am Unterricht teil */
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -9,7 +9,7 @@ extern "C" {
|
||||||
|
|
||||||
struct unit;
|
struct unit;
|
||||||
void academy_teaching_bonus(struct unit *u, skill_t sk, int academy);
|
void academy_teaching_bonus(struct unit *u, skill_t sk, int academy);
|
||||||
bool academy_can_teach(struct unit *teacher, struct unit *student, skill_t sk);
|
bool academy_can_teach(struct unit *teacher, struct unit *scholar, skill_t sk);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
161
src/automate.c
Normal file
161
src/automate.c
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
#include <platform.h>
|
||||||
|
|
||||||
|
#include "kernel/faction.h"
|
||||||
|
#include "kernel/messages.h"
|
||||||
|
#include "kernel/order.h"
|
||||||
|
#include "kernel/region.h"
|
||||||
|
#include "kernel/unit.h"
|
||||||
|
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
#include "automate.h"
|
||||||
|
#include "keyword.h"
|
||||||
|
#include "laws.h"
|
||||||
|
#include "study.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
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) {
|
||||||
|
/* sort by level, descending: */
|
||||||
|
return b->level - a->level;
|
||||||
|
}
|
||||||
|
/* order by skill */
|
||||||
|
return (int)a->sk - (int)b->sk;
|
||||||
|
}
|
||||||
|
|
||||||
|
int autostudy_init(scholar scholars[], int max_scholars, region *r)
|
||||||
|
{
|
||||||
|
unit *u;
|
||||||
|
int nscholars = 0;
|
||||||
|
|
||||||
|
for (u = r->units; u; u = u->next) {
|
||||||
|
keyword_t kwd = getkeyword(u->thisorder);
|
||||||
|
if (kwd == K_AUTOSTUDY) {
|
||||||
|
if (long_order_allowed(u) && unit_can_study(u)) {
|
||||||
|
scholar * st = scholars + nscholars;
|
||||||
|
if (++nscholars == max_scholars) {
|
||||||
|
log_fatal("you must increase MAXSCHOLARS");
|
||||||
|
}
|
||||||
|
st->u = u;
|
||||||
|
init_order(u->thisorder, u->faction->locale);
|
||||||
|
st->sk = getskill(u->faction->locale);
|
||||||
|
st->level = effskill_study(u, st->sk);
|
||||||
|
st->learn = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_race_nolearn", "race",
|
||||||
|
u_race(u)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nscholars > 0) {
|
||||||
|
qsort(scholars, nscholars, sizeof(scholar), cmp_scholars);
|
||||||
|
}
|
||||||
|
return nscholars;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void teaching(scholar *s, int n) {
|
||||||
|
assert(n <= s->u->number);
|
||||||
|
s->learn += n;
|
||||||
|
s->u->flags |= UFL_LONGACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void learning(scholar *s, int n) {
|
||||||
|
assert(n <= s->u->number);
|
||||||
|
s->learn += n;
|
||||||
|
s->u->flags |= UFL_LONGACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void autostudy_run(scholar scholars[], int nscholars)
|
||||||
|
{
|
||||||
|
int ti = 0;
|
||||||
|
while (ti != nscholars) {
|
||||||
|
skill_t sk = scholars[ti].sk;
|
||||||
|
int t, s, se, ts = 0, tt = 0, si = ti;
|
||||||
|
for (se = ti; se != nscholars && scholars[se].sk == sk; ++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; ++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[ti].level - TEACHDIFFERENCE > scholars[si].level; ++si) {
|
||||||
|
tt += scholars[si].u->number;
|
||||||
|
}
|
||||||
|
if (si == se) {
|
||||||
|
/* there are no students, so standard learning only */
|
||||||
|
for (t = ti; t != se; ++t) {
|
||||||
|
learning(scholars + t, scholars[t].u->number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* invariant: unit ti can still teach i students */
|
||||||
|
int i = scholars[ti].u->number * STUDENTS_PER_TEACHER;
|
||||||
|
/* invariant: unit si has n students that can still be taught */
|
||||||
|
int n = scholars[si].u->number;
|
||||||
|
for (t = ti, s = si; t != si && s != se; ) {
|
||||||
|
if (i > n) {
|
||||||
|
/* t has more than enough teaching capacity for s */
|
||||||
|
i -= n;
|
||||||
|
teaching(scholars + s, n);
|
||||||
|
learning(scholars + s, scholars[s].u->number);
|
||||||
|
/* next student, please: */
|
||||||
|
if (++s == se) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
n = scholars[s].u->number;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* s gets partial credit and we need a new teacher */
|
||||||
|
teaching(scholars + s, i);
|
||||||
|
|
||||||
|
/* we are done with this teacher. any remaining people are regular learners: */
|
||||||
|
if (scholars[t].u->number > 1) {
|
||||||
|
/* remain = number - ceil(taught/10); */
|
||||||
|
int remain = (STUDENTS_PER_TEACHER * scholars[t].u->number - i + STUDENTS_PER_TEACHER - 1) / STUDENTS_PER_TEACHER;
|
||||||
|
learning(scholars + t, remain);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we want a new teacher for s. if any exists, it's next in the sequence. */
|
||||||
|
if (++t == si) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (scholars[t].level - TEACHDIFFERENCE < scholars[s].level) {
|
||||||
|
/* next teacher cannot teach, we must skip students. */
|
||||||
|
do {
|
||||||
|
learning(scholars + s, (n - i));
|
||||||
|
i = 0;
|
||||||
|
if (++s == se) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
n = scholars[s].u->number;
|
||||||
|
} while (scholars[t].level - TEACHDIFFERENCE < scholars[s].level);
|
||||||
|
}
|
||||||
|
i = scholars[t].u->number * STUDENTS_PER_TEACHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ti = se;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAXSCHOLARS 128
|
||||||
|
|
||||||
|
void do_autostudy(region *r)
|
||||||
|
{
|
||||||
|
scholar scholars[MAXSCHOLARS];
|
||||||
|
int i, nscholars = autostudy_init(scholars, MAXSCHOLARS, 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);
|
||||||
|
}
|
||||||
|
}
|
43
src/automate.h
Normal file
43
src/automate.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 1998-2018, Enno Rehling <enno@eressea.de>
|
||||||
|
Katja Zedel <katze@felidae.kn-bremen.de
|
||||||
|
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef H_GC_AUTOMATE
|
||||||
|
#define H_GC_AUTOMATE
|
||||||
|
|
||||||
|
#include "skill.h"
|
||||||
|
|
||||||
|
struct region;
|
||||||
|
struct unit;
|
||||||
|
|
||||||
|
typedef struct scholar {
|
||||||
|
struct unit *u;
|
||||||
|
skill_t sk;
|
||||||
|
int level;
|
||||||
|
int learn;
|
||||||
|
} scholar;
|
||||||
|
|
||||||
|
#define STUDENTS_PER_TEACHER 10
|
||||||
|
|
||||||
|
void do_autostudy(struct region *r);
|
||||||
|
|
||||||
|
int autostudy_init(scholar scholars[], int max_scholars, struct region *r);
|
||||||
|
void autostudy_run(scholar scholars[], int nscholars);
|
||||||
|
|
||||||
|
#endif
|
114
src/automate.test.c
Normal file
114
src/automate.test.c
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <platform.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "automate.h"
|
||||||
|
|
||||||
|
#include "kernel/faction.h"
|
||||||
|
#include "kernel/order.h"
|
||||||
|
#include "kernel/region.h"
|
||||||
|
#include "kernel/unit.h"
|
||||||
|
|
||||||
|
#include "tests.h"
|
||||||
|
|
||||||
|
#include <CuTest.h>
|
||||||
|
|
||||||
|
static void test_autostudy_init(CuTest *tc) {
|
||||||
|
scholar scholars[4];
|
||||||
|
unit *u1, *u2, *u3;
|
||||||
|
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_ENTERTAINMENT]);
|
||||||
|
test_create_unit(f, r);
|
||||||
|
u2 = test_create_unit(f, r);
|
||||||
|
u2->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]);
|
||||||
|
set_level(u2, SK_ENTERTAINMENT, 2);
|
||||||
|
u3 = test_create_unit(f, r);
|
||||||
|
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
|
scholars[3].u = NULL;
|
||||||
|
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, r));
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
CuAssertPtrEquals(tc, NULL, scholars[3].u);
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_autostudy_run(CuTest *tc) {
|
||||||
|
scholar scholars[4];
|
||||||
|
unit *u1, *u2, *u3;
|
||||||
|
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_ENTERTAINMENT]);
|
||||||
|
set_number(u1, 2);
|
||||||
|
set_level(u1, SK_ENTERTAINMENT, 2);
|
||||||
|
u2 = test_create_unit(f, r);
|
||||||
|
u2->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]);
|
||||||
|
set_number(u2, 10);
|
||||||
|
u3 = test_create_unit(f, r);
|
||||||
|
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
|
set_number(u3, 15);
|
||||||
|
scholars[3].u = NULL;
|
||||||
|
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, r));
|
||||||
|
autostudy_run(scholars, 3);
|
||||||
|
CuAssertIntEquals(tc, 0, scholars[0].learn);
|
||||||
|
CuAssertIntEquals(tc, 20, scholars[1].learn);
|
||||||
|
CuAssertIntEquals(tc, 15, scholars[2].learn);
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_autostudy_run_noteachers(CuTest *tc) {
|
||||||
|
scholar scholars[4];
|
||||||
|
unit *u1, *u2, *u3;
|
||||||
|
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_LUMBERJACK]);
|
||||||
|
set_number(u1, 2);
|
||||||
|
set_level(u1, SK_ENTERTAINMENT, 2);
|
||||||
|
u2 = test_create_unit(f, r);
|
||||||
|
u2->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]);
|
||||||
|
set_number(u2, 10);
|
||||||
|
u3 = test_create_unit(f, r);
|
||||||
|
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
|
set_number(u3, 15);
|
||||||
|
scholars[3].u = NULL;
|
||||||
|
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, r));
|
||||||
|
autostudy_run(scholars, 3);
|
||||||
|
CuAssertIntEquals(tc, 2, scholars[0].learn);
|
||||||
|
CuAssertIntEquals(tc, 10, scholars[1].learn);
|
||||||
|
CuAssertIntEquals(tc, 15, scholars[2].learn);
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
|
CuSuite *get_automate_suite(void)
|
||||||
|
{
|
||||||
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_autostudy_init);
|
||||||
|
SUITE_ADD_TEST(suite, test_autostudy_run);
|
||||||
|
SUITE_ADD_TEST(suite, test_autostudy_run_noteachers);
|
||||||
|
return suite;
|
||||||
|
}
|
|
@ -135,7 +135,8 @@ const char *parameters[MAXPARAMS] = {
|
||||||
"GRUPPE",
|
"GRUPPE",
|
||||||
"PARTEITARNUNG",
|
"PARTEITARNUNG",
|
||||||
"BAEUME",
|
"BAEUME",
|
||||||
"ALLIANZ"
|
"ALLIANZ",
|
||||||
|
"AUTO"
|
||||||
};
|
};
|
||||||
|
|
||||||
int findoption(const char *s, const struct locale *lang)
|
int findoption(const char *s, const struct locale *lang)
|
||||||
|
|
|
@ -84,7 +84,7 @@ char* get_command(const order *ord, const struct locale *lang, char *sbuffer, si
|
||||||
sbs_strcat(&sbs, str);
|
sbs_strcat(&sbs, str);
|
||||||
if (ord->id < 0) {
|
if (ord->id < 0) {
|
||||||
skill_t sk = (skill_t)(100+ord->id);
|
skill_t sk = (skill_t)(100+ord->id);
|
||||||
assert(kwd == K_STUDY && sk != SK_MAGIC && sk < MAXSKILLS);
|
assert((kwd == K_STUDY || kwd == K_AUTOSTUDY) && sk != SK_MAGIC && sk < MAXSKILLS);
|
||||||
str = skillname(sk, lang);
|
str = skillname(sk, lang);
|
||||||
if (str) {
|
if (str) {
|
||||||
if (strchr(str, ' ') == NULL) {
|
if (strchr(str, ' ') == NULL) {
|
||||||
|
@ -214,12 +214,12 @@ static int create_data(keyword_t kwd, const char *s,
|
||||||
order_data *data;
|
order_data *data;
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
assert(kwd!=NOKEYWORD);
|
assert(kwd != NOKEYWORD);
|
||||||
|
|
||||||
if (!s || *s == 0) {
|
if (!s || *s == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (kwd==K_STUDY) {
|
if (kwd == K_STUDY || kwd == K_AUTOSTUDY) {
|
||||||
const char * sptr = s;
|
const char * sptr = s;
|
||||||
skill_t sk = get_skill(parse_token_depr(&sptr), lang);
|
skill_t sk = get_skill(parse_token_depr(&sptr), lang);
|
||||||
if (sk != SK_MAGIC && sk != NOSKILL) {
|
if (sk != SK_MAGIC && sk != NOSKILL) {
|
||||||
|
@ -332,6 +332,14 @@ order *parse_order(const char *s, const struct locale * lang)
|
||||||
sptr = sp;
|
sptr = sp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (kwd == K_STUDY) {
|
||||||
|
const char *sp = sptr;
|
||||||
|
p = parse_token_depr(&sp);
|
||||||
|
if (p && isparam(p, lang, P_AUTO)) {
|
||||||
|
kwd = K_AUTOSTUDY;
|
||||||
|
sptr = sp;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (kwd != NOKEYWORD) {
|
if (kwd != NOKEYWORD) {
|
||||||
order *ord = (order *)malloc(sizeof(order));
|
order *ord = (order *)malloc(sizeof(order));
|
||||||
create_order_i(ord, kwd, sptr, persistent, noerror, lang);
|
create_order_i(ord, kwd, sptr, persistent, noerror, lang);
|
||||||
|
@ -366,6 +374,7 @@ bool is_repeated(keyword_t kwd)
|
||||||
case K_STEAL:
|
case K_STEAL:
|
||||||
case K_SABOTAGE:
|
case K_SABOTAGE:
|
||||||
case K_STUDY:
|
case K_STUDY:
|
||||||
|
case K_AUTOSTUDY:
|
||||||
case K_TEACH:
|
case K_TEACH:
|
||||||
case K_GROW:
|
case K_GROW:
|
||||||
case K_PLANT:
|
case K_PLANT:
|
||||||
|
@ -406,6 +415,7 @@ bool is_exclusive(const order * ord)
|
||||||
case K_STEAL:
|
case K_STEAL:
|
||||||
case K_SABOTAGE:
|
case K_SABOTAGE:
|
||||||
case K_STUDY:
|
case K_STUDY:
|
||||||
|
case K_AUTOSTUDY:
|
||||||
case K_TEACH:
|
case K_TEACH:
|
||||||
case K_GROW:
|
case K_GROW:
|
||||||
case K_PLANT:
|
case K_PLANT:
|
||||||
|
@ -447,6 +457,7 @@ bool is_long(keyword_t kwd)
|
||||||
case K_STEAL:
|
case K_STEAL:
|
||||||
case K_SABOTAGE:
|
case K_SABOTAGE:
|
||||||
case K_STUDY:
|
case K_STUDY:
|
||||||
|
case K_AUTOSTUDY:
|
||||||
case K_TEACH:
|
case K_TEACH:
|
||||||
case K_GROW:
|
case K_GROW:
|
||||||
case K_PLANT:
|
case K_PLANT:
|
||||||
|
@ -541,7 +552,7 @@ keyword_t init_order(const struct order *ord, const struct locale *lang)
|
||||||
|
|
||||||
assert(sk < MAXSKILLS);
|
assert(sk < MAXSKILLS);
|
||||||
assert(lang);
|
assert(lang);
|
||||||
assert(kwd == K_STUDY);
|
assert(kwd == K_STUDY || kwd == K_AUTOSTUDY);
|
||||||
str = skillname(sk, lang);
|
str = skillname(sk, lang);
|
||||||
if (strchr(str, ' ') == NULL) {
|
if (strchr(str, ' ') == NULL) {
|
||||||
init_tokens_str(str);
|
init_tokens_str(str);
|
||||||
|
@ -575,7 +586,7 @@ keyword_t init_order_depr(const struct order *ord)
|
||||||
{
|
{
|
||||||
if (ord) {
|
if (ord) {
|
||||||
keyword_t kwd = ORD_KEYWORD(ord);
|
keyword_t kwd = ORD_KEYWORD(ord);
|
||||||
assert(kwd != K_STUDY);
|
assert(kwd != K_STUDY && kwd != K_AUTOSTUDY);
|
||||||
}
|
}
|
||||||
return init_order(ord, NULL);
|
return init_order(ord, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,30 @@ static void test_parse_make(CuTest *tc) {
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_parse_autostudy(CuTest *tc) {
|
||||||
|
char cmd[32];
|
||||||
|
order *ord;
|
||||||
|
struct locale * lang;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
lang = get_or_create_locale("en");
|
||||||
|
locale_setstring(lang, mkname("skill", skillnames[SK_ENTERTAINMENT]), "Entertainment");
|
||||||
|
locale_setstring(lang, keyword(K_STUDY), "STUDY");
|
||||||
|
locale_setstring(lang, keyword(K_AUTOSTUDY), "AUTOSTUDY");
|
||||||
|
locale_setstring(lang, parameters[P_AUTO], "AUTO");
|
||||||
|
init_locale(lang);
|
||||||
|
|
||||||
|
ord = parse_order("STUDY AUTO Entertainment", lang);
|
||||||
|
CuAssertPtrNotNull(tc, ord);
|
||||||
|
CuAssertIntEquals(tc, K_AUTOSTUDY, getkeyword(ord));
|
||||||
|
CuAssertStrEquals(tc, "AUTOSTUDY Entertainment", get_command(ord, lang, cmd, sizeof(cmd)));
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, K_AUTOSTUDY, init_order(ord, lang));
|
||||||
|
CuAssertStrEquals(tc, "Entertainment", getstrtoken());
|
||||||
|
free_order(ord);
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_parse_make_temp(CuTest *tc) {
|
static void test_parse_make_temp(CuTest *tc) {
|
||||||
char cmd[32];
|
char cmd[32];
|
||||||
order *ord;
|
order *ord;
|
||||||
|
@ -130,7 +154,7 @@ static void test_parse_make_temp(CuTest *tc) {
|
||||||
CuAssertIntEquals(tc, K_MAKETEMP, getkeyword(ord));
|
CuAssertIntEquals(tc, K_MAKETEMP, getkeyword(ord));
|
||||||
CuAssertStrEquals(tc, "MAKETEMP herp", get_command(ord, lang, cmd, sizeof(cmd)));
|
CuAssertStrEquals(tc, "MAKETEMP herp", get_command(ord, lang, cmd, sizeof(cmd)));
|
||||||
|
|
||||||
CuAssertIntEquals(tc, K_MAKETEMP, init_order_depr(ord));
|
CuAssertIntEquals(tc, K_MAKETEMP, init_order(ord, lang));
|
||||||
CuAssertStrEquals(tc, "herp", getstrtoken());
|
CuAssertStrEquals(tc, "herp", getstrtoken());
|
||||||
free_order(ord);
|
free_order(ord);
|
||||||
test_teardown();
|
test_teardown();
|
||||||
|
@ -153,7 +177,7 @@ static void test_parse_maketemp(CuTest *tc) {
|
||||||
CuAssertPtrNotNull(tc, ord);
|
CuAssertPtrNotNull(tc, ord);
|
||||||
CuAssertStrEquals(tc, "MAKETEMP herp", get_command(ord, lang, cmd, sizeof(cmd)));
|
CuAssertStrEquals(tc, "MAKETEMP herp", get_command(ord, lang, cmd, sizeof(cmd)));
|
||||||
CuAssertIntEquals(tc, K_MAKETEMP, getkeyword(ord));
|
CuAssertIntEquals(tc, K_MAKETEMP, getkeyword(ord));
|
||||||
CuAssertIntEquals(tc, K_MAKETEMP, init_order_depr(ord));
|
CuAssertIntEquals(tc, K_MAKETEMP, init_order(ord, lang));
|
||||||
CuAssertStrEquals(tc, "herp", getstrtoken());
|
CuAssertStrEquals(tc, "herp", getstrtoken());
|
||||||
free_order(ord);
|
free_order(ord);
|
||||||
test_teardown();
|
test_teardown();
|
||||||
|
@ -167,7 +191,7 @@ static void test_init_order(CuTest *tc) {
|
||||||
|
|
||||||
lang = get_or_create_locale("en");
|
lang = get_or_create_locale("en");
|
||||||
ord = create_order(K_MAKETEMP, lang, "hurr durr");
|
ord = create_order(K_MAKETEMP, lang, "hurr durr");
|
||||||
CuAssertIntEquals(tc, K_MAKETEMP, init_order_depr(ord));
|
CuAssertIntEquals(tc, K_MAKETEMP, init_order(ord, lang));
|
||||||
CuAssertStrEquals(tc, "hurr", getstrtoken());
|
CuAssertStrEquals(tc, "hurr", getstrtoken());
|
||||||
CuAssertStrEquals(tc, "durr", getstrtoken());
|
CuAssertStrEquals(tc, "durr", getstrtoken());
|
||||||
free_order(ord);
|
free_order(ord);
|
||||||
|
@ -548,6 +572,7 @@ CuSuite *get_order_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_study_order_quoted);
|
SUITE_ADD_TEST(suite, test_study_order_quoted);
|
||||||
SUITE_ADD_TEST(suite, test_parse_order);
|
SUITE_ADD_TEST(suite, test_parse_order);
|
||||||
SUITE_ADD_TEST(suite, test_parse_make);
|
SUITE_ADD_TEST(suite, test_parse_make);
|
||||||
|
SUITE_ADD_TEST(suite, test_parse_autostudy);
|
||||||
SUITE_ADD_TEST(suite, test_parse_make_temp);
|
SUITE_ADD_TEST(suite, test_parse_make_temp);
|
||||||
SUITE_ADD_TEST(suite, test_parse_maketemp);
|
SUITE_ADD_TEST(suite, test_parse_maketemp);
|
||||||
SUITE_ADD_TEST(suite, test_init_order);
|
SUITE_ADD_TEST(suite, test_init_order);
|
||||||
|
|
|
@ -130,6 +130,7 @@ typedef enum {
|
||||||
P_FACTIONSTEALTH,
|
P_FACTIONSTEALTH,
|
||||||
P_TREES,
|
P_TREES,
|
||||||
P_ALLIANCE,
|
P_ALLIANCE,
|
||||||
|
P_AUTO,
|
||||||
MAXPARAMS,
|
MAXPARAMS,
|
||||||
NOPARAM
|
NOPARAM
|
||||||
} param_t;
|
} param_t;
|
||||||
|
|
|
@ -1310,13 +1310,12 @@ int eff_skill(const unit * u, const skill *sv, const region *r)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int effskill_study(const unit * u, skill_t sk, const region * r)
|
int effskill_study(const unit * u, skill_t sk)
|
||||||
{
|
{
|
||||||
skill *sv = unit_skill(u, sk);
|
skill *sv = unit_skill(u, sk);
|
||||||
if (sv && sv->level > 0) {
|
if (sv && sv->level > 0) {
|
||||||
int mlevel = sv->level;
|
int mlevel = sv->level;
|
||||||
if (!r) r = u->region;
|
mlevel += get_modifier(u, sv->id, sv->level, u->region, true);
|
||||||
mlevel += get_modifier(u, sv->id, sv->level, r, true);
|
|
||||||
if (mlevel > 0)
|
if (mlevel > 0)
|
||||||
return mlevel;
|
return mlevel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ extern "C" {
|
||||||
void clone_men(const struct unit *src, struct unit *dst, int n); /* like transfer, but do not subtract from src */
|
void clone_men(const struct unit *src, struct unit *dst, int n); /* like transfer, but do not subtract from src */
|
||||||
|
|
||||||
int eff_skill(const struct unit *u, const struct skill *sv, const struct region *r);
|
int eff_skill(const struct unit *u, const struct skill *sv, const struct region *r);
|
||||||
int effskill_study(const struct unit *u, skill_t sk, const struct region *r);
|
int effskill_study(const struct unit *u, skill_t sk);
|
||||||
|
|
||||||
int get_modifier(const struct unit *u, skill_t sk, int level,
|
int get_modifier(const struct unit *u, skill_t sk, int level,
|
||||||
const struct region *r, bool noitem);
|
const struct region *r, bool noitem);
|
||||||
|
|
|
@ -149,5 +149,6 @@ const char *keywords[MAXKEYWORDS] = {
|
||||||
"promote",
|
"promote",
|
||||||
"pay",
|
"pay",
|
||||||
"loot",
|
"loot",
|
||||||
|
"autostudy",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ extern "C"
|
||||||
K_PROMOTION,
|
K_PROMOTION,
|
||||||
K_PAY,
|
K_PAY,
|
||||||
K_LOOT,
|
K_LOOT,
|
||||||
|
K_AUTOSTUDY,
|
||||||
MAXKEYWORDS,
|
MAXKEYWORDS,
|
||||||
NOKEYWORD
|
NOKEYWORD
|
||||||
} keyword_t;
|
} keyword_t;
|
||||||
|
|
33
src/laws.c
33
src/laws.c
|
@ -26,6 +26,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <modules/gmcmd.h>
|
#include <modules/gmcmd.h>
|
||||||
|
|
||||||
#include "alchemy.h"
|
#include "alchemy.h"
|
||||||
|
#include "automate.h"
|
||||||
#include "battle.h"
|
#include "battle.h"
|
||||||
#include "economy.h"
|
#include "economy.h"
|
||||||
#include "keyword.h"
|
#include "keyword.h"
|
||||||
|
@ -3636,6 +3637,24 @@ void add_proc_unit(int priority, void(*process) (unit *), const char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool long_order_allowed(const unit *u)
|
||||||
|
{
|
||||||
|
const region *r = u->region;
|
||||||
|
if (fval(u, UFL_LONGACTION)) {
|
||||||
|
/* this message was already given in laws.update_long_order
|
||||||
|
cmistake(u, ord, 52, MSG_PRODUCE);
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (fval(r->terrain, SEA_REGION)
|
||||||
|
&& u_race(u) != get_race(RC_AQUARIAN)
|
||||||
|
&& !(u_race(u)->flags & RCF_SWIM)) {
|
||||||
|
/* error message disabled by popular demand */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* per priority, execute processors in order from PR_GLOBAL down to PR_ORDER */
|
/* per priority, execute processors in order from PR_GLOBAL down to PR_ORDER */
|
||||||
void process(void)
|
void process(void)
|
||||||
{
|
{
|
||||||
|
@ -3705,16 +3724,7 @@ void process(void)
|
||||||
cmistake(u, ord, 224, MSG_MAGIC);
|
cmistake(u, ord, 224, MSG_MAGIC);
|
||||||
ord = NULL;
|
ord = NULL;
|
||||||
}
|
}
|
||||||
else if (fval(u, UFL_LONGACTION)) {
|
else if (!long_order_allowed(u)) {
|
||||||
/* this message was already given in laws.update_long_order
|
|
||||||
cmistake(u, ord, 52, MSG_PRODUCE);
|
|
||||||
*/
|
|
||||||
ord = NULL;
|
|
||||||
}
|
|
||||||
else if (fval(r->terrain, SEA_REGION)
|
|
||||||
&& u_race(u) != get_race(RC_AQUARIAN)
|
|
||||||
&& !(u_race(u)->flags & RCF_SWIM)) {
|
|
||||||
/* error message disabled by popular demand */
|
|
||||||
ord = NULL;
|
ord = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4001,6 +4011,7 @@ void init_processor(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
p += 10;
|
p += 10;
|
||||||
|
add_proc_region(p, do_autostudy, "study automation");
|
||||||
add_proc_order(p, K_TEACH, teach_cmd, PROC_THISORDER | PROC_LONGORDER,
|
add_proc_order(p, K_TEACH, teach_cmd, PROC_THISORDER | PROC_LONGORDER,
|
||||||
"Lehren");
|
"Lehren");
|
||||||
p += 10;
|
p += 10;
|
||||||
|
@ -4155,7 +4166,7 @@ void update_subscriptions(void)
|
||||||
/** determine if unit can be seen by faction
|
/** determine if unit can be seen by faction
|
||||||
* @param f -- the observiong faction
|
* @param f -- the observiong faction
|
||||||
* @param u -- the unit that is observed
|
* @param u -- the unit that is observed
|
||||||
* @param r -- the region that u is obesrved in (see below)
|
* @param r -- the region that u is obesrved from (see below)
|
||||||
* @param m -- terrain modifier to stealth
|
* @param m -- terrain modifier to stealth
|
||||||
*
|
*
|
||||||
* r kann != u->region sein, wenn es um Durchreisen geht,
|
* r kann != u->region sein, wenn es um Durchreisen geht,
|
||||||
|
|
|
@ -66,6 +66,7 @@ extern "C" {
|
||||||
void update_long_order(struct unit *u);
|
void update_long_order(struct unit *u);
|
||||||
void sinkships(struct region * r);
|
void sinkships(struct region * r);
|
||||||
void do_enter(struct region *r, bool is_final_attempt);
|
void do_enter(struct region *r, bool is_final_attempt);
|
||||||
|
bool long_order_allowed(const struct unit *u);
|
||||||
|
|
||||||
int password_cmd(struct unit *u, struct order *ord);
|
int password_cmd(struct unit *u, struct order *ord);
|
||||||
int banner_cmd(struct unit *u, struct order *ord);
|
int banner_cmd(struct unit *u, struct order *ord);
|
||||||
|
|
|
@ -1759,6 +1759,34 @@ static void test_nmr_timeout(CuTest *tc) {
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_long_orders(CuTest *tc) {
|
||||||
|
unit *u;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||||
|
CuAssertTrue(tc, long_order_allowed(u));
|
||||||
|
u->flags |= UFL_LONGACTION;
|
||||||
|
CuAssertTrue(tc, !long_order_allowed(u));
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_long_order_on_ocean(CuTest *tc) {
|
||||||
|
unit *u;
|
||||||
|
race * rc;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
rc = test_create_race("pikachu");
|
||||||
|
u = test_create_unit(test_create_faction(rc), test_create_ocean(0, 0));
|
||||||
|
CuAssertTrue(tc, !long_order_allowed(u));
|
||||||
|
rc->flags |= RCF_SWIM;
|
||||||
|
CuAssertTrue(tc, long_order_allowed(u));
|
||||||
|
|
||||||
|
rc = test_create_race("aquarian");
|
||||||
|
u = test_create_unit(test_create_faction(rc), u->region);
|
||||||
|
CuAssertTrue(tc, long_order_allowed(u));
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_laws_suite(void)
|
CuSuite *get_laws_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
@ -1831,6 +1859,8 @@ CuSuite *get_laws_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_cansee_ring);
|
SUITE_ADD_TEST(suite, test_cansee_ring);
|
||||||
SUITE_ADD_TEST(suite, test_cansee_sphere);
|
SUITE_ADD_TEST(suite, test_cansee_sphere);
|
||||||
SUITE_ADD_TEST(suite, test_nmr_timeout);
|
SUITE_ADD_TEST(suite, test_nmr_timeout);
|
||||||
|
SUITE_ADD_TEST(suite, test_long_orders);
|
||||||
|
SUITE_ADD_TEST(suite, test_long_order_on_ocean);
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
94
src/study.c
94
src/study.c
|
@ -69,7 +69,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#define TEACH_ALL 1
|
#define TEACH_ALL 1
|
||||||
#define TEACH_FRIENDS
|
#define TEACH_FRIENDS
|
||||||
|
|
||||||
static skill_t getskill(const struct locale *lang)
|
skill_t getskill(const struct locale *lang)
|
||||||
{
|
{
|
||||||
char token[128];
|
char token[128];
|
||||||
const char * s = gettoken(token, sizeof(token));
|
const char * s = gettoken(token, sizeof(token));
|
||||||
|
@ -195,37 +195,37 @@ const attrib_type at_learning = {
|
||||||
|
|
||||||
#define EXPERIENCEDAYS 10
|
#define EXPERIENCEDAYS 10
|
||||||
|
|
||||||
static int study_days(unit * student, skill_t sk)
|
static int study_days(unit * scholar, skill_t sk)
|
||||||
{
|
{
|
||||||
int speed = STUDYDAYS;
|
int speed = STUDYDAYS;
|
||||||
if (u_race(student)->study_speed) {
|
if (u_race(scholar)->study_speed) {
|
||||||
speed += u_race(student)->study_speed[sk];
|
speed += u_race(scholar)->study_speed[sk];
|
||||||
if (speed < STUDYDAYS) {
|
if (speed < STUDYDAYS) {
|
||||||
skill *sv = unit_skill(student, sk);
|
skill *sv = unit_skill(scholar, sk);
|
||||||
if (sv == 0) {
|
if (sv == 0) {
|
||||||
speed = STUDYDAYS;
|
speed = STUDYDAYS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return student->number * speed;
|
return scholar->number * speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk,
|
teach_unit(unit * teacher, unit * scholar, int nteaching, skill_t sk,
|
||||||
bool report, int *academy_students)
|
bool report, int *academy_students)
|
||||||
{
|
{
|
||||||
teaching_info *teach = NULL;
|
teaching_info *teach = NULL;
|
||||||
attrib *a;
|
attrib *a;
|
||||||
int students;
|
int students;
|
||||||
|
|
||||||
if (magic_lowskill(student)) {
|
if (magic_lowskill(scholar)) {
|
||||||
cmistake(teacher, teacher->thisorder, 292, MSG_EVENT);
|
cmistake(teacher, teacher->thisorder, 292, MSG_EVENT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
students = student->number;
|
students = scholar->number;
|
||||||
/* subtract already taught students */
|
/* subtract already taught students */
|
||||||
a = a_find(student->attribs, &at_learning);
|
a = a_find(scholar->attribs, &at_learning);
|
||||||
if (a != NULL) {
|
if (a != NULL) {
|
||||||
teach = (teaching_info *)a->data.v;
|
teach = (teaching_info *)a->data.v;
|
||||||
students -= teach->students;
|
students -= teach->students;
|
||||||
|
@ -235,18 +235,18 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk,
|
||||||
|
|
||||||
if (students > 0) {
|
if (students > 0) {
|
||||||
if (teach == NULL) {
|
if (teach == NULL) {
|
||||||
a = a_add(&student->attribs, a_new(&at_learning));
|
a = a_add(&scholar->attribs, a_new(&at_learning));
|
||||||
teach = (teaching_info *)a->data.v;
|
teach = (teaching_info *)a->data.v;
|
||||||
}
|
}
|
||||||
selist_push(&teach->teachers, teacher);
|
selist_push(&teach->teachers, teacher);
|
||||||
teach->days += students * STUDYDAYS;
|
teach->days += students * STUDYDAYS;
|
||||||
teach->students += students;
|
teach->students += students;
|
||||||
|
|
||||||
if (student->building && teacher->building == student->building) {
|
if (scholar->building && teacher->building == scholar->building) {
|
||||||
/* Solange Akademien groessenbeschraenkt sind, sollte Lehrer und
|
/* Solange Akademien groessenbeschraenkt sind, sollte Lehrer und
|
||||||
* Student auch in unterschiedlichen Gebaeuden stehen duerfen */
|
* Student auch in unterschiedlichen Gebaeuden stehen duerfen */
|
||||||
/* FIXME comment contradicts implementation */
|
/* FIXME comment contradicts implementation */
|
||||||
if (academy_can_teach(teacher, student, sk)) {
|
if (academy_can_teach(teacher, scholar, sk)) {
|
||||||
/* Jeder Schueler zusaetzlich +10 Tage wenn in Uni. */
|
/* Jeder Schueler zusaetzlich +10 Tage wenn in Uni. */
|
||||||
teach->days += students * EXPERIENCEDAYS; /* learning erhoehen */
|
teach->days += students * EXPERIENCEDAYS; /* learning erhoehen */
|
||||||
/* Lehrer zusaetzlich +1 Tag pro Schueler. */
|
/* Lehrer zusaetzlich +1 Tag pro Schueler. */
|
||||||
|
@ -304,7 +304,7 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
#if TEACH_ALL
|
#if TEACH_ALL
|
||||||
if (getparam(teacher->faction->locale) == P_ANY) {
|
if (getparam(teacher->faction->locale) == P_ANY) {
|
||||||
skill_t sk;
|
skill_t sk;
|
||||||
unit *student;
|
unit *scholar;
|
||||||
skill_t teachskill[MAXSKILLS];
|
skill_t teachskill[MAXSKILLS];
|
||||||
int t = 0;
|
int t = 0;
|
||||||
|
|
||||||
|
@ -313,15 +313,15 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
teachskill[t] = getskill(teacher->faction->locale);
|
teachskill[t] = getskill(teacher->faction->locale);
|
||||||
} while (sk != NOSKILL);
|
} while (sk != NOSKILL);
|
||||||
|
|
||||||
for (student = r->units; teaching > 0 && student; student = student->next) {
|
for (scholar = r->units; teaching > 0 && scholar; scholar = scholar->next) {
|
||||||
if (LongHunger(student)) {
|
if (LongHunger(scholar)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (student->faction == teacher->faction) {
|
else if (scholar->faction == teacher->faction) {
|
||||||
if (getkeyword(student->thisorder) == K_STUDY) {
|
if (getkeyword(scholar->thisorder) == K_STUDY) {
|
||||||
/* Input ist nun von student->thisorder !! */
|
/* Input ist nun von student->thisorder !! */
|
||||||
init_order(student->thisorder, student->faction->locale);
|
init_order(scholar->thisorder, scholar->faction->locale);
|
||||||
sk = getskill(student->faction->locale);
|
sk = getskill(scholar->faction->locale);
|
||||||
if (sk != NOSKILL && teachskill[0] != NOSKILL) {
|
if (sk != NOSKILL && teachskill[0] != NOSKILL) {
|
||||||
for (t = 0; teachskill[t] != NOSKILL; ++t) {
|
for (t = 0; teachskill[t] != NOSKILL; ++t) {
|
||||||
if (sk == teachskill[t]) {
|
if (sk == teachskill[t]) {
|
||||||
|
@ -331,20 +331,20 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
sk = teachskill[t];
|
sk = teachskill[t];
|
||||||
}
|
}
|
||||||
if (sk != NOSKILL
|
if (sk != NOSKILL
|
||||||
&& effskill_study(teacher, sk, 0) - TEACHDIFFERENCE > effskill_study(student, sk, 0)) {
|
&& effskill_study(teacher, sk) - TEACHDIFFERENCE > effskill_study(scholar, sk)) {
|
||||||
teaching -= teach_unit(teacher, student, teaching, sk, true, &academy_students);
|
teaching -= teach_unit(teacher, scholar, teaching, sk, true, &academy_students);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef TEACH_FRIENDS
|
#ifdef TEACH_FRIENDS
|
||||||
else if (alliedunit(teacher, student->faction, HELP_GUARD)) {
|
else if (alliedunit(teacher, scholar->faction, HELP_GUARD)) {
|
||||||
if (getkeyword(student->thisorder) == K_STUDY) {
|
if (getkeyword(scholar->thisorder) == K_STUDY) {
|
||||||
/* Input ist nun von student->thisorder !! */
|
/* Input ist nun von student->thisorder !! */
|
||||||
init_order(student->thisorder, student->faction->locale);
|
init_order(scholar->thisorder, scholar->faction->locale);
|
||||||
sk = getskill(student->faction->locale);
|
sk = getskill(scholar->faction->locale);
|
||||||
if (sk != NOSKILL
|
if (sk != NOSKILL
|
||||||
&& effskill_study(teacher, sk, 0) - TEACHDIFFERENCE >= effskill(student, sk, 0)) {
|
&& effskill_study(teacher, sk) - TEACHDIFFERENCE >= effskill(scholar, sk, NULL)) {
|
||||||
teaching -= teach_unit(teacher, student, teaching, sk, true, &academy_students);
|
teaching -= teach_unit(teacher, scholar, teaching, sk, true, &academy_students);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,15 +363,15 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
|
|
||||||
while (!parser_end()) {
|
while (!parser_end()) {
|
||||||
skill_t sk;
|
skill_t sk;
|
||||||
unit *student;
|
unit *scholar;
|
||||||
bool feedback;
|
bool feedback;
|
||||||
|
|
||||||
getunit(r, teacher->faction, &student);
|
getunit(r, teacher->faction, &scholar);
|
||||||
++count;
|
++count;
|
||||||
|
|
||||||
/* Falls die Unit nicht gefunden wird, Fehler melden */
|
/* Falls die Unit nicht gefunden wird, Fehler melden */
|
||||||
|
|
||||||
if (!student) {
|
if (!scholar) {
|
||||||
char tbuf[20];
|
char tbuf[20];
|
||||||
const char *uid;
|
const char *uid;
|
||||||
const char *token;
|
const char *token;
|
||||||
|
@ -403,8 +403,8 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
feedback = teacher->faction == student->faction
|
feedback = teacher->faction == scholar->faction
|
||||||
|| alliedunit(student, teacher->faction, HELP_GUARD);
|
|| alliedunit(scholar, teacher->faction, HELP_GUARD);
|
||||||
|
|
||||||
/* Neuen Befehl zusammenbauen. TEMP-Einheiten werden automatisch in
|
/* Neuen Befehl zusammenbauen. TEMP-Einheiten werden automatisch in
|
||||||
* ihre neuen Nummern uebersetzt. */
|
* ihre neuen Nummern uebersetzt. */
|
||||||
|
@ -412,31 +412,31 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
strncat(zOrder, " ", sz - 1);
|
strncat(zOrder, " ", sz - 1);
|
||||||
--sz;
|
--sz;
|
||||||
}
|
}
|
||||||
sz -= str_strlcpy(zOrder + 4096 - sz, itoa36(student->no), sz);
|
sz -= str_strlcpy(zOrder + 4096 - sz, itoa36(scholar->no), sz);
|
||||||
|
|
||||||
if (getkeyword(student->thisorder) != K_STUDY) {
|
if (getkeyword(scholar->thisorder) != K_STUDY) {
|
||||||
ADDMSG(&teacher->faction->msgs,
|
ADDMSG(&teacher->faction->msgs,
|
||||||
msg_feedback(teacher, ord, "teach_nolearn", "student", student));
|
msg_feedback(teacher, ord, "teach_nolearn", "student", scholar));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Input ist nun von student->thisorder !! */
|
/* Input ist nun von student->thisorder !! */
|
||||||
parser_pushstate();
|
parser_pushstate();
|
||||||
init_order(student->thisorder, student->faction->locale);
|
init_order(scholar->thisorder, scholar->faction->locale);
|
||||||
sk = getskill(student->faction->locale);
|
sk = getskill(scholar->faction->locale);
|
||||||
parser_popstate();
|
parser_popstate();
|
||||||
|
|
||||||
if (sk == NOSKILL) {
|
if (sk == NOSKILL) {
|
||||||
ADDMSG(&teacher->faction->msgs,
|
ADDMSG(&teacher->faction->msgs,
|
||||||
msg_feedback(teacher, ord, "teach_nolearn", "student", student));
|
msg_feedback(teacher, ord, "teach_nolearn", "student", scholar));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effskill_study(student, sk, 0) > effskill_study(teacher, sk, 0)
|
if (effskill_study(scholar, sk) > effskill_study(teacher, sk)
|
||||||
- TEACHDIFFERENCE) {
|
- TEACHDIFFERENCE) {
|
||||||
if (feedback) {
|
if (feedback) {
|
||||||
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "teach_asgood",
|
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "teach_asgood",
|
||||||
"student", student));
|
"student", scholar));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -444,18 +444,18 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
/* ist der Magier schon spezialisiert, so versteht er nur noch
|
/* ist der Magier schon spezialisiert, so versteht er nur noch
|
||||||
* Lehrer seines Gebietes */
|
* Lehrer seines Gebietes */
|
||||||
sc_mage *mage1 = get_mage_depr(teacher);
|
sc_mage *mage1 = get_mage_depr(teacher);
|
||||||
sc_mage *mage2 = get_mage_depr(student);
|
sc_mage *mage2 = get_mage_depr(scholar);
|
||||||
if (mage2 && mage1 && mage2->magietyp != M_GRAY
|
if (mage2 && mage1 && mage2->magietyp != M_GRAY
|
||||||
&& mage1->magietyp != mage2->magietyp) {
|
&& mage1->magietyp != mage2->magietyp) {
|
||||||
if (feedback) {
|
if (feedback) {
|
||||||
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord,
|
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord,
|
||||||
"error_different_magic", "target", student));
|
"error_different_magic", "target", scholar));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sk_academy = sk;
|
sk_academy = sk;
|
||||||
teaching -= teach_unit(teacher, student, teaching, sk, false, &academy_students);
|
teaching -= teach_unit(teacher, scholar, teaching, sk, false, &academy_students);
|
||||||
}
|
}
|
||||||
new_order = create_order(K_TEACH, teacher->faction->locale, "%s", zOrder);
|
new_order = create_order(K_TEACH, teacher->faction->locale, "%s", zOrder);
|
||||||
replace_order(&teacher->orders, ord, new_order);
|
replace_order(&teacher->orders, ord, new_order);
|
||||||
|
@ -766,9 +766,6 @@ int study_cmd(unit * u, order * ord)
|
||||||
days *= 2;
|
days *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fval(u, UFL_HUNGER))
|
|
||||||
days /= 2;
|
|
||||||
|
|
||||||
learn_skill(u, sk, days);
|
learn_skill(u, sk, days);
|
||||||
if (a != NULL) {
|
if (a != NULL) {
|
||||||
if (teach->teachers) {
|
if (teach->teachers) {
|
||||||
|
@ -832,6 +829,9 @@ void learn_skill(unit *u, skill_t sk, int days) {
|
||||||
int leveldays = STUDYDAYS * u->number;
|
int leveldays = STUDYDAYS * u->number;
|
||||||
int weeks = 0;
|
int weeks = 0;
|
||||||
|
|
||||||
|
if (fval(u, UFL_HUNGER)) {
|
||||||
|
days /= 2;
|
||||||
|
}
|
||||||
assert(sk >= 0 && sk < MAXSKILLS);
|
assert(sk >= 0 && sk < MAXSKILLS);
|
||||||
if (inject_learn_fun) {
|
if (inject_learn_fun) {
|
||||||
inject_learn_fun(u, sk, days);
|
inject_learn_fun(u, sk, days);
|
||||||
|
|
|
@ -33,6 +33,7 @@ extern "C" {
|
||||||
int study_cmd(struct unit *u, struct order *ord);
|
int study_cmd(struct unit *u, struct order *ord);
|
||||||
|
|
||||||
magic_t getmagicskill(const struct locale *lang);
|
magic_t getmagicskill(const struct locale *lang);
|
||||||
|
skill_t getskill(const struct locale *lang);
|
||||||
bool is_migrant(struct unit *u);
|
bool is_migrant(struct unit *u);
|
||||||
int study_cost(struct unit *u, skill_t talent);
|
int study_cost(struct unit *u, skill_t talent);
|
||||||
|
|
||||||
|
|
|
@ -89,15 +89,15 @@ static void setup_teacher(study_fixture *fix, skill_t sk) {
|
||||||
setup_locale(lang);
|
setup_locale(lang);
|
||||||
fix->u = test_create_unit(f, r);
|
fix->u = test_create_unit(f, r);
|
||||||
assert(fix->u);
|
assert(fix->u);
|
||||||
fix->u->thisorder = create_order(K_STUDY, f->locale, "%s", skillnames[sk]);
|
fix->u->thisorder = create_order(K_STUDY, f->locale, skillnames[sk]);
|
||||||
|
|
||||||
fix->teachers[0] = test_create_unit(f, r);
|
fix->teachers[0] = test_create_unit(f, r);
|
||||||
assert(fix->teachers[0]);
|
assert(fix->teachers[0]);
|
||||||
fix->teachers[0]->thisorder = create_order(K_TEACH, f->locale, "%s", itoa36(fix->u->no));
|
fix->teachers[0]->thisorder = create_order(K_TEACH, f->locale, itoa36(fix->u->no));
|
||||||
|
|
||||||
fix->teachers[1] = test_create_unit(f, r);
|
fix->teachers[1] = test_create_unit(f, r);
|
||||||
assert(fix->teachers[1]);
|
assert(fix->teachers[1]);
|
||||||
fix->teachers[1]->thisorder = create_order(K_TEACH, f->locale, "%s", itoa36(fix->u->no));
|
fix->teachers[1]->thisorder = create_order(K_TEACH, f->locale, itoa36(fix->u->no));
|
||||||
test_clear_messages(f);
|
test_clear_messages(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ static void test_study_no_teacher(CuTest *tc) {
|
||||||
CuAssertPtrNotNull(tc, sv = unit_skill(fix.u, SK_CROSSBOW));
|
CuAssertPtrNotNull(tc, sv = unit_skill(fix.u, SK_CROSSBOW));
|
||||||
CuAssertIntEquals(tc, 1, sv->level);
|
CuAssertIntEquals(tc, 1, sv->level);
|
||||||
CuAssertIntEquals(tc, 2, sv->weeks);
|
CuAssertIntEquals(tc, 2, sv->weeks);
|
||||||
CuAssertPtrEquals(tc, 0, test_get_last_message(fix.u->faction->msgs));
|
CuAssertPtrEquals(tc, NULL, test_get_last_message(fix.u->faction->msgs));
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ static void test_study_with_teacher(CuTest *tc) {
|
||||||
setup_teacher(&fix, SK_CROSSBOW);
|
setup_teacher(&fix, SK_CROSSBOW);
|
||||||
set_level(fix.teachers[0], SK_CROSSBOW, TEACHDIFFERENCE);
|
set_level(fix.teachers[0], SK_CROSSBOW, TEACHDIFFERENCE);
|
||||||
teach_cmd(fix.teachers[0], fix.teachers[0]->thisorder);
|
teach_cmd(fix.teachers[0], fix.teachers[0]->thisorder);
|
||||||
CuAssertPtrEquals(tc, 0, test_get_last_message(fix.u->faction->msgs));
|
CuAssertPtrEquals(tc, NULL, test_get_last_message(fix.u->faction->msgs));
|
||||||
study_cmd(fix.u, fix.u->thisorder);
|
study_cmd(fix.u, fix.u->thisorder);
|
||||||
CuAssertPtrNotNull(tc, sv = unit_skill(fix.u, SK_CROSSBOW));
|
CuAssertPtrNotNull(tc, sv = unit_skill(fix.u, SK_CROSSBOW));
|
||||||
CuAssertIntEquals(tc, 1, sv->level);
|
CuAssertIntEquals(tc, 1, sv->level);
|
||||||
|
@ -288,7 +288,7 @@ static void test_academy_bonus(CuTest *tc) {
|
||||||
u1 = test_create_unit(u->faction, u->region);
|
u1 = test_create_unit(u->faction, u->region);
|
||||||
u3 = test_create_unit(u->faction, u->region);
|
u3 = test_create_unit(u->faction, u->region);
|
||||||
u0->thisorder = create_order(K_TEACH, loc, "%s %s", itoa36(u3->no), itoa36(u1->no));
|
u0->thisorder = create_order(K_TEACH, loc, "%s %s", itoa36(u3->no), itoa36(u1->no));
|
||||||
u->thisorder = create_order(K_TEACH, loc, "%s", itoa36(u1->no));
|
u->thisorder = create_order(K_TEACH, loc, itoa36(u1->no));
|
||||||
u1->thisorder = create_order(K_STUDY, loc, skillnames[SK_CROSSBOW]);
|
u1->thisorder = create_order(K_STUDY, loc, skillnames[SK_CROSSBOW]);
|
||||||
u3->thisorder = create_order(K_STUDY, loc, skillnames[SK_CROSSBOW]);
|
u3->thisorder = create_order(K_STUDY, loc, skillnames[SK_CROSSBOW]);
|
||||||
|
|
||||||
|
@ -405,7 +405,7 @@ static void test_study_magic(CuTest *tc) {
|
||||||
f = test_create_faction(NULL);
|
f = test_create_faction(NULL);
|
||||||
lang = f->locale;
|
lang = f->locale;
|
||||||
u = test_create_unit(f, test_create_region(0, 0, NULL));
|
u = test_create_unit(f, test_create_region(0, 0, NULL));
|
||||||
u->thisorder = create_order(K_STUDY, lang, "%s", skillnames[SK_MAGIC]);
|
u->thisorder = create_order(K_STUDY, lang, skillnames[SK_MAGIC]);
|
||||||
itype = test_create_silver();
|
itype = test_create_silver();
|
||||||
|
|
||||||
CuAssertIntEquals(tc, -1, study_cmd(u, u->thisorder));
|
CuAssertIntEquals(tc, -1, study_cmd(u, u->thisorder));
|
||||||
|
@ -423,7 +423,7 @@ static void test_study_magic(CuTest *tc) {
|
||||||
CuAssertIntEquals(tc, M_GWYRRD, f->magiegebiet);
|
CuAssertIntEquals(tc, M_GWYRRD, f->magiegebiet);
|
||||||
CuAssertIntEquals(tc, 0, i_get(u->items, itype));
|
CuAssertIntEquals(tc, 0, i_get(u->items, itype));
|
||||||
CuAssertPtrNotNull(tc, get_mage_depr(u));
|
CuAssertPtrNotNull(tc, get_mage_depr(u));
|
||||||
CuAssertPtrEquals(tc, 0, test_find_messagetype(f->msgs, "error65"));
|
CuAssertPtrEquals(tc, NULL, test_find_messagetype(f->msgs, "error65"));
|
||||||
CuAssertIntEquals(tc, M_GWYRRD, get_mage_depr(u)->magietyp);
|
CuAssertIntEquals(tc, M_GWYRRD, get_mage_depr(u)->magietyp);
|
||||||
|
|
||||||
test_teardown();
|
test_teardown();
|
||||||
|
@ -491,12 +491,12 @@ static void test_teach_magic(CuTest *tc) {
|
||||||
f = test_create_faction(NULL);
|
f = test_create_faction(NULL);
|
||||||
f->magiegebiet = M_GWYRRD;
|
f->magiegebiet = M_GWYRRD;
|
||||||
u = test_create_unit(f, test_create_region(0, 0, NULL));
|
u = test_create_unit(f, test_create_region(0, 0, NULL));
|
||||||
u->thisorder = create_order(K_STUDY, f->locale, "%s", skillnames[SK_MAGIC]);
|
u->thisorder = create_order(K_STUDY, f->locale, skillnames[SK_MAGIC]);
|
||||||
i_change(&u->items, itype, study_cost(u, SK_MAGIC));
|
i_change(&u->items, itype, study_cost(u, SK_MAGIC));
|
||||||
ut = test_create_unit(f, u->region);
|
ut = test_create_unit(f, u->region);
|
||||||
set_level(ut, SK_MAGIC, TEACHDIFFERENCE);
|
set_level(ut, SK_MAGIC, TEACHDIFFERENCE);
|
||||||
create_mage(ut, M_GWYRRD);
|
create_mage(ut, M_GWYRRD);
|
||||||
ut->thisorder = create_order(K_TEACH, f->locale, "%s", itoa36(u->no));
|
ut->thisorder = create_order(K_TEACH, f->locale, itoa36(u->no));
|
||||||
learn_inject();
|
learn_inject();
|
||||||
teach_cmd(ut, ut->thisorder);
|
teach_cmd(ut, ut->thisorder);
|
||||||
study_cmd(u, u->thisorder);
|
study_cmd(u, u->thisorder);
|
||||||
|
|
|
@ -93,7 +93,6 @@ int RunAllTests(int argc, char *argv[])
|
||||||
ADD_SUITE(xerewards);
|
ADD_SUITE(xerewards);
|
||||||
/* kernel */
|
/* kernel */
|
||||||
ADD_SUITE(academy);
|
ADD_SUITE(academy);
|
||||||
ADD_SUITE(alchemy);
|
|
||||||
ADD_SUITE(alliance);
|
ADD_SUITE(alliance);
|
||||||
ADD_SUITE(ally);
|
ADD_SUITE(ally);
|
||||||
ADD_SUITE(building);
|
ADD_SUITE(building);
|
||||||
|
@ -121,6 +120,8 @@ int RunAllTests(int argc, char *argv[])
|
||||||
ADD_SUITE(spells);
|
ADD_SUITE(spells);
|
||||||
ADD_SUITE(unit);
|
ADD_SUITE(unit);
|
||||||
/* gamecode */
|
/* gamecode */
|
||||||
|
ADD_SUITE(alchemy);
|
||||||
|
ADD_SUITE(automate);
|
||||||
ADD_SUITE(battle);
|
ADD_SUITE(battle);
|
||||||
ADD_SUITE(calendar);
|
ADD_SUITE(calendar);
|
||||||
ADD_SUITE(creport);
|
ADD_SUITE(creport);
|
||||||
|
|
BIN
src/util/.DS_Store
vendored
Normal file
BIN
src/util/.DS_Store
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue