Merge branch 'develop' of https://github.com/ennorehling/eressea into develop

This commit is contained in:
Enno Rehling 2018-09-09 16:05:31 +02:00
commit 10c47d339e
15 changed files with 174 additions and 74 deletions

2
clibs

@ -1 +1 @@
Subproject commit 66a891b383f1a51bb0d4e5cf002530f7f70bf7f4
Subproject commit d86c8525489d7f11b7ba13e101bb59ecf160b871

View File

@ -28,6 +28,9 @@ if [ -e orders.$TURN ]; then
files="$files orders.$TURN"
fi
echo "backup turn $TURN, game $GAME, files: $files"
if [ -d reports ] ; then
tar cjf backup/$TURN-reports.tar.bz2 reports
fi
tar cjf backup/$TURN.tar.bz2 $files
echo "uploading game-$GAME/$TURN.tar.bz2"
curl -s -n -T backup/$TURN.tar.bz2 https://dav.box.com/dav/Eressea/game-$GAME/$TURN.tar.bz2

View File

@ -2864,6 +2864,9 @@ msgstr "der Schatten"
msgid "ALLES"
msgstr "ALLES"
msgid "AUTO"
msgstr "AUTO"
msgid "undead_postfix_2"
msgstr "der Finsternis"
@ -5958,6 +5961,10 @@ msgctxt "keyword"
msgid "maketemp"
msgstr "MACHE TEMP"
msgctxt "keyword"
msgid "autostudy"
msgstr "LERNE AUTO"
msgctxt "spell"
msgid "reanimate"
msgstr "Wiederbelebung"

View File

@ -2510,6 +2510,9 @@ msgstr "halfling foot"
msgid "ALLES"
msgstr "ALL"
msgid "AUTO"
msgstr "AUTO"
msgctxt "race"
msgid "songdragon_d"
msgstr "song dragons"
@ -5268,7 +5271,11 @@ msgstr "berserkers blood potions"
msgctxt "keyword"
msgid "maketemp"
msgstr "MAKETEMP"
msgstr "MAKE TEMP"
msgctxt "keyword"
msgid "autostudy"
msgstr "LEARN AUTO"
msgctxt "spell"
msgid "reanimate"

View File

@ -12,6 +12,30 @@ function setup()
eressea.settings.set("rules.peasants.growth.factor", "0")
end
function test_study_auto()
local r = region.create(0, 0, "plain")
local f = faction.create("human")
local u = unit.create(f, r, 1)
u:add_order("LERN AUT Waffenbau")
assert_equal("LERNE AUTO Waffenbau", u:get_order(0))
process_orders()
assert_equal(1, u:get_skill("weaponsmithing"))
end
function test_study_auto_expensive()
local r = region.create(0, 0, "plain")
local f = faction.create("human")
local u = unit.create(f, r, 1)
u:add_order("LERNE AUTO Magie")
assert_equal("LERNE Magie", u:get_order(0))
u:clear_orders()
u:add_order("LERN AUT Taktik")
assert_equal("LERNE Taktik", u:get_order(0))
u:clear_orders()
u:add_order("LERN AUT Waffenbau")
assert_equal("LERNE AUTO Waffenbau", u:get_order(0))
end
function test_calendar()
assert_equal("winter", get_season(1011))
assert_equal("spring", get_season(1012))

View File

@ -42,7 +42,8 @@ function test_build_watch()
process_orders()
assert_not_nil(u.building)
if 5 ~= u.building.size then
for k,v in f.messages do
-- debug logging to find intermittent errors
for k,v in ipairs(f.messages) do
print(v)
end
end

View File

@ -24,7 +24,7 @@ end
function test_study()
local r = region.create(0, 0, "plain")
local f = faction.create("human", "test@example.com", "de")
local f = faction.create("human")
local u = unit.create(f, r, 1)
u:add_order("LERNEN Armbrust")
process_orders()
@ -33,7 +33,7 @@ end
function test_study_expensive()
local r = region.create(0, 0, "plain")
local f = faction.create("human", "test@example.com", "de")
local f = faction.create("human")
local u = unit.create(f, r, 1)
eressea.settings.set("skills.cost.alchemy", "50")
u:add_order("LERNEN Alchemie")
@ -45,7 +45,7 @@ end
function test_unit_spells()
local r = region.create(0, 0, "plain")
local f = faction.create("human", "test@example.com", "de")
local f = faction.create("human")
local u = unit.create(f, r, 1)
u.magic = "gray"
u:set_skill("magic", 1)
@ -75,7 +75,7 @@ end
function test_study_no_teacher()
local r = region.create(0, 0, "plain")
local f = faction.create("human", "test@example.com", "de")
local f = faction.create("human")
local u1 = make_student(f, r, 1)
u1:set_skill("crossbow", 1)
process_orders()
@ -84,7 +84,7 @@ end
function test_study_with_teacher()
local r = region.create(0, 0, "plain")
local f = faction.create("human", "test@example.com", "de")
local f = faction.create("human")
local u1 = make_student(f, r, 1)
make_teacher(u1)
@ -95,7 +95,7 @@ end
function test_study_too_many_students()
local r = region.create(0, 0, "plain")
local f = faction.create("human", "test@example.com", "de")
local f = faction.create("human")
local u1 = make_student(f, r, 20, "Taktik")
u1.name = "Student"
u1:add_item("money", 201*u1.number)
@ -106,7 +106,7 @@ end
function test_study_multiple_teachers()
local r = region.create(0, 0, "plain")
local f = faction.create("human", "test@example.com", "de")
local f = faction.create("human")
local u1 = make_student(f, r, 20, "Taktik")
u1.name = "Student"
u1:add_item("money", 201*u1.number)

View File

@ -38,14 +38,14 @@ int autostudy_init(scholar scholars[], int max_scholars, region *r)
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;
st->u = u;
if (++nscholars == max_scholars) {
log_fatal("you must increase MAXSCHOLARS");
}
}
else {
ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_race_nolearn", "race",

View File

@ -141,7 +141,8 @@ int stream_order(struct stream *out, const struct order *ord, const struct local
if (ord->id < 0) {
skill_t sk = (skill_t)(100 + ord->id);
assert(kwd == K_STUDY && sk != SK_MAGIC && sk < MAXSKILLS);
assert(kwd == K_AUTOSTUDY || kwd == K_STUDY);
assert(sk != SK_MAGIC && sk < MAXSKILLS);
text = skillname(sk, lang);
if (strchr(text, ' ') != NULL) {
swrite(" '", 1, 2, out);
@ -310,12 +311,13 @@ order *parse_order(const char *s, const struct locale * lang)
assert(lang);
assert(s);
if (*s != 0) {
char token[32];
keyword_t kwd = NOKEYWORD;
const char *sptr = s;
bool persistent = false, noerror = false;
const char * p;
char * p;
p = *sptr ? parse_token_depr(&sptr) : 0;
p = parse_token(&sptr, token, sizeof(token));
if (p) {
while (*p == '!' || *p == '@') {
if (*p == '!') noerror = true;
@ -326,7 +328,7 @@ order *parse_order(const char *s, const struct locale * lang)
}
if (kwd == K_MAKE) {
const char *sp = sptr;
p = parse_token_depr(&sp);
p = parse_token(&sp, token, sizeof(token));
if (p && isparam(p, lang, P_TEMP)) {
kwd = K_MAKETEMP;
sptr = sp;
@ -334,10 +336,15 @@ order *parse_order(const char *s, const struct locale * lang)
}
else if (kwd == K_STUDY) {
const char *sp = sptr;
p = parse_token_depr(&sp);
p = parse_token(&sp, token, sizeof(token));
if (p && isparam(p, lang, P_AUTO)) {
kwd = K_AUTOSTUDY;
skill_t sk;
sptr = sp;
p = parse_token(&sp, token, sizeof(token));
sk = get_skill(p, lang);
if (!expensive_skill(sk)) {
kwd = K_AUTOSTUDY;
}
}
}
if (kwd != NOKEYWORD) {

View File

@ -121,6 +121,8 @@ static void test_parse_autostudy(CuTest *tc) {
test_setup();
lang = get_or_create_locale("en");
locale_setstring(lang, mkname("skill", skillnames[SK_ENTERTAINMENT]), "Entertainment");
locale_setstring(lang, mkname("skill", skillnames[SK_MAGIC]), "Magic");
locale_setstring(lang, mkname("skill", skillnames[SK_TACTICS]), "Tactics");
locale_setstring(lang, keyword(K_STUDY), "STUDY");
locale_setstring(lang, keyword(K_AUTOSTUDY), "AUTOSTUDY");
locale_setstring(lang, parameters[P_AUTO], "AUTO");
@ -134,6 +136,17 @@ static void test_parse_autostudy(CuTest *tc) {
CuAssertIntEquals(tc, K_AUTOSTUDY, init_order(ord, lang));
CuAssertStrEquals(tc, "Entertainment", getstrtoken());
free_order(ord);
ord = parse_order("STUDY AUTO Magic", lang);
CuAssertIntEquals(tc, K_STUDY, getkeyword(ord));
CuAssertStrEquals(tc, "STUDY Magic", get_command(ord, lang, cmd, sizeof(cmd)));
free_order(ord);
ord = parse_order("STUDY AUTO Tactics", lang);
CuAssertIntEquals(tc, K_STUDY, getkeyword(ord));
CuAssertStrEquals(tc, "STUDY Tactics", get_command(ord, lang, cmd, sizeof(cmd)));
free_order(ord);
test_teardown();
}

View File

@ -113,3 +113,38 @@ skill_t get_skill(const char *s, const struct locale * lang)
return result;
}
int skill_cost(skill_t sk) {
static int config;
static int costs[MAXSKILLS];
int cost;
switch (sk) {
case SK_SPY:
cost = 100;
break;
case SK_TACTICS:
case SK_HERBALISM:
case SK_ALCHEMY:
cost = 200;
break;
default:
cost = -1;
}
if (config_changed(&config)) {
memset(costs, 0, sizeof(costs));
}
if (costs[sk] == 0) {
char buffer[256];
sprintf(buffer, "skills.cost.%s", skillnames[sk]);
costs[sk] = config_get_int(buffer, cost);
}
if (costs[sk] >= 0) {
return costs[sk];
}
return (cost > 0) ? cost : 0;
}
bool expensive_skill(skill_t sk) {
return (sk == SK_MAGIC) || skill_cost(sk) > 0;
}

View File

@ -49,5 +49,7 @@ void init_skills(const struct locale *lang);
void init_skill(const struct locale *lang, skill_t kwd, const char *str);
void enable_skill(skill_t sk, bool enabled);
bool skill_enabled(skill_t sk);
int skill_cost(skill_t sk);
bool expensive_skill(skill_t sk);
#endif

View File

@ -1,6 +1,8 @@
#include <platform.h>
#include "skill.h"
#include "kernel/config.h"
#include "util/language.h"
#include "skill.h"
#include "tests.h"
#include <CuTest.h>
@ -38,12 +40,34 @@ static void test_get_skill(CuTest *tc) {
test_teardown();
}
static void test_skill_cost(CuTest *tc) {
test_setup();
CuAssertTrue(tc, expensive_skill(SK_MAGIC));
CuAssertTrue(tc, expensive_skill(SK_TACTICS));
CuAssertTrue(tc, expensive_skill(SK_SPY));
CuAssertTrue(tc, expensive_skill(SK_ALCHEMY));
CuAssertTrue(tc, expensive_skill(SK_HERBALISM));
CuAssertTrue(tc, !expensive_skill(SK_CROSSBOW));
CuAssertIntEquals(tc, 100, skill_cost(SK_SPY));
CuAssertIntEquals(tc, 200, skill_cost(SK_TACTICS));
CuAssertIntEquals(tc, 200, skill_cost(SK_ALCHEMY));
CuAssertIntEquals(tc, 200, skill_cost(SK_HERBALISM));
CuAssertIntEquals(tc, 0, skill_cost(SK_CROSSBOW));
config_set_int("skills.cost.crossbow", 300);
CuAssertIntEquals(tc, 300, skill_cost(SK_CROSSBOW));
CuAssertTrue(tc, expensive_skill(SK_CROSSBOW));
test_teardown();
}
CuSuite *get_skill_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_init_skill);
SUITE_ADD_TEST(suite, test_init_skills);
SUITE_ADD_TEST(suite, test_get_skill);
SUITE_ADD_TEST(suite, test_skill_cost);
return suite;
}

View File

@ -130,47 +130,23 @@ bool magic_lowskill(unit * u)
return u_race(u) == toad_rc;
}
/* ------------------------------------------------------------- */
int study_cost(struct unit *u, skill_t sk)
{
static int config;
static int costs[MAXSKILLS];
int cost = -1;
if (sk == SK_MAGIC) {
int next_level = 1 + (u ? get_level(u, sk) : 0);
static int config;
static int cost;
/* Die Magiekosten betragen 50+Summe(50*Stufe) */
/* 'Stufe' ist dabei die naechste zu erreichende Stufe */
cost = config_get_int("skills.cost.magic", 50);
return cost * (1 + ((next_level + next_level * next_level) / 2));
if (config_changed(&config)) {
cost = config_get_int("skills.cost.magic", 50);
}
if (cost > 0) {
int next_level = 1 + (u ? get_level(u, sk) : 0);
return cost * (1 + ((next_level + next_level * next_level) / 2));
}
return cost;
}
else switch (sk) {
case SK_SPY:
cost = 100;
break;
case SK_TACTICS:
case SK_HERBALISM:
case SK_ALCHEMY:
cost = 200;
break;
default:
cost = -1;
}
if (config_changed(&config)) {
memset(costs, 0, sizeof(costs));
}
if (costs[sk] == 0) {
char buffer[256];
sprintf(buffer, "skills.cost.%s", skillnames[sk]);
costs[sk] = config_get_int(buffer, cost);
}
if (costs[sk] >= 0) {
return costs[sk];
}
return (cost > 0) ? cost : 0;
return skill_cost(sk);
}
/* ------------------------------------------------------------- */

View File

@ -29,26 +29,9 @@ extern "C" {
struct unit;
struct selist;
int teach_cmd(struct unit *u, struct order *ord);
int study_cmd(struct unit *u, struct order *ord);
magic_t getmagicskill(const struct locale *lang);
skill_t getskill(const struct locale *lang);
bool is_migrant(struct unit *u);
int study_cost(struct unit *u, skill_t talent);
typedef void(*learn_fun)(struct unit *u, skill_t sk, int days);
#define STUDYDAYS 30
void learn_skill(struct unit *u, skill_t sk, int days);
void reduce_skill_days(struct unit *u, skill_t sk, int days);
void produceexp(struct unit *u, skill_t sk, int n);
void produceexp_ex(struct unit *u, skill_t sk, int n, learn_fun learn);
void demon_skillchange(struct unit *u);
#define TEACHNUMBER 10
typedef struct teaching_info {
struct selist *teachers;
int students;
@ -57,6 +40,24 @@ extern "C" {
extern const struct attrib_type at_learning;
int teach_cmd(struct unit *u, struct order *ord);
int study_cmd(struct unit *u, struct order *ord);
magic_t getmagicskill(const struct locale *lang);
skill_t getskill(const struct locale *lang);
bool is_migrant(struct unit *u);
int study_cost(struct unit *u, skill_t sk);
typedef void(*learn_fun)(struct unit *u, skill_t sk, int days);
void learn_skill(struct unit *u, skill_t sk, int days);
void reduce_skill_days(struct unit *u, skill_t sk, int days);
void produceexp(struct unit *u, skill_t sk, int n);
void produceexp_ex(struct unit *u, skill_t sk, int n, learn_fun learn);
void demon_skillchange(struct unit *u);
void inject_learn(learn_fun fun);
#ifdef __cplusplus