diff --git a/src/automate.c b/src/automate.c index 2f188f352..ec4ea83d8 100644 --- a/src/automate.c +++ b/src/automate.c @@ -1,6 +1,7 @@ #include #include "kernel/faction.h" +#include "kernel/messages.h" #include "kernel/order.h" #include "kernel/region.h" #include "kernel/unit.h" @@ -9,6 +10,7 @@ #include "automate.h" #include "keyword.h" +#include "laws.h" #include "study.h" #include @@ -34,15 +36,21 @@ int autostudy_init(scholar scholars[], int max_scholars, region *r) for (u = r->units; u; u = u->next) { keyword_t kwd = getkeyword(u->thisorder); if (kwd == K_AUTOSTUDY) { - scholar * st = scholars + nscholars; - if (++nscholars == max_scholars) { - log_fatal("you must increase MAXSCHOLARS"); + 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))); } - 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; } } if (nscholars > 0) { @@ -54,11 +62,13 @@ int autostudy_init(scholar scholars[], int max_scholars, region *r) static void teaching(scholar *s, int n) { assert(n <= s->u->number); s->learn += n; + fset(s->u, UFL_LONGACTION); } static void learning(scholar *s, int n) { assert(n <= s->u->number); s->learn += n; + fset(s->u, UFL_LONGACTION); } void autostudy_run(scholar scholars[], int nscholars) diff --git a/src/automate.test.c b/src/automate.test.c index 999cb25d4..a77376668 100644 --- a/src/automate.test.c +++ b/src/automate.test.c @@ -73,6 +73,7 @@ static void test_autostudy_run(CuTest *tc) { 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) { @@ -100,6 +101,7 @@ static void test_autostudy_run_noteachers(CuTest *tc) { 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) diff --git a/src/laws.c b/src/laws.c index 80c730c8f..68f2894b3 100644 --- a/src/laws.c +++ b/src/laws.c @@ -3637,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 */ void process(void) { @@ -3706,16 +3724,7 @@ void process(void) cmistake(u, ord, 224, MSG_MAGIC); ord = NULL; } - else if (fval(u, UFL_LONGACTION)) { - /* 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 */ + else if (!long_order_allowed(u)) { ord = NULL; } } @@ -4157,7 +4166,7 @@ void update_subscriptions(void) /** determine if unit can be seen by faction * @param f -- the observiong faction * @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 * * r kann != u->region sein, wenn es um Durchreisen geht, diff --git a/src/laws.h b/src/laws.h index ae2c712ca..0b5db17c7 100755 --- a/src/laws.h +++ b/src/laws.h @@ -66,6 +66,7 @@ extern "C" { void update_long_order(struct unit *u); void sinkships(struct region * r); 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 banner_cmd(struct unit *u, struct order *ord); diff --git a/src/laws.test.c b/src/laws.test.c index 8d13b7c81..c7c7a6682 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -1759,6 +1759,34 @@ static void test_nmr_timeout(CuTest *tc) { 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 *suite = CuSuiteNew(); @@ -1831,6 +1859,8 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_cansee_ring); SUITE_ADD_TEST(suite, test_cansee_sphere); 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; } diff --git a/src/study.test.c b/src/study.test.c index c1d0b0841..a63be7cf1 100644 --- a/src/study.test.c +++ b/src/study.test.c @@ -89,15 +89,15 @@ static void setup_teacher(study_fixture *fix, skill_t sk) { setup_locale(lang); fix->u = test_create_unit(f, r); 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); 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); 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); } @@ -110,7 +110,7 @@ static void test_study_no_teacher(CuTest *tc) { CuAssertPtrNotNull(tc, sv = unit_skill(fix.u, SK_CROSSBOW)); CuAssertIntEquals(tc, 1, sv->level); 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(); } @@ -121,7 +121,7 @@ static void test_study_with_teacher(CuTest *tc) { setup_teacher(&fix, SK_CROSSBOW); set_level(fix.teachers[0], SK_CROSSBOW, TEACHDIFFERENCE); 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); CuAssertPtrNotNull(tc, sv = unit_skill(fix.u, SK_CROSSBOW)); CuAssertIntEquals(tc, 1, sv->level); @@ -288,7 +288,7 @@ static void test_academy_bonus(CuTest *tc) { u1 = 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)); - 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]); 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); lang = f->locale; 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(); 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, 0, i_get(u->items, itype)); 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); test_teardown(); @@ -491,12 +491,12 @@ static void test_teach_magic(CuTest *tc) { f = test_create_faction(NULL); f->magiegebiet = M_GWYRRD; 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)); ut = test_create_unit(f, u->region); set_level(ut, SK_MAGIC, TEACHDIFFERENCE); 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(); teach_cmd(ut, ut->thisorder); study_cmd(u, u->thisorder);