diff --git a/src/guard.c b/src/guard.c index ee26e467b..4b0c63e22 100644 --- a/src/guard.c +++ b/src/guard.c @@ -128,7 +128,7 @@ bool is_guard(const struct unit * u) unit *is_guarded(region * r, unit * u) { unit *u2; - int noguards = 1; + bool noguards = true; if (!fval(r, RF_GUARDED)) { return NULL; @@ -140,7 +140,7 @@ unit *is_guarded(region * r, unit * u) for (u2 = r->units; u2; u2 = u2->next) { if (is_guardian_r(u2)) { - noguards = 0; + noguards = false; if (is_guardian_u(u2, u)) { /* u2 is our guard. stop processing (we might have to go further next time) */ return u2; diff --git a/src/kernel/race.c b/src/kernel/race.c index f28c5ed2f..decc3b7bb 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -369,10 +369,3 @@ void register_race_description_function(race_desc_func func, const char *name) { void register_race_name_function(race_name_func func, const char *name) { register_function((pf_generic)func, name); } - -char * race_namegen(const struct race *rc, struct unit *u) { - if (rc->generate_name) { - rc->generate_name(u); - } - return NULL; -} diff --git a/src/kernel/race.h b/src/kernel/race.h index 022d09c86..6673676bd 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -252,7 +252,6 @@ extern "C" { const char *raceprefix(const struct unit *u); void register_race_name_function(race_name_func, const char *); void register_race_description_function(race_desc_func, const char *); - char * race_namegen(const struct race *rc, struct unit *u); #ifdef __cplusplus } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 4aff7d118..f06c4c252 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1480,15 +1480,9 @@ void default_name(const unit *u, char name[], int len) { void name_unit(unit * u) { - if (u_race(u)->generate_name) { - char *gen_name = race_namegen(u_race(u), u); - if (gen_name) { - free(u->_name); - u->_name = gen_name; - } - else { - unit_setname(u, racename(u->faction->locale, u, u_race(u))); - } + const race *rc = u_race(u); + if (rc->generate_name) { + rc->generate_name(u); } else { char name[32]; diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index c4b1f46ed..752627144 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -468,6 +468,24 @@ static void test_renumber_unit(CuTest *tc) { test_cleanup(); } +static void gen_name(unit *u) +{ + unit_setname(u, "Hodor"); +} + +static void test_name_unit(CuTest *tc) { + race *rc; + unit * u; + + test_setup(); + rc = test_create_race("skeleton"); + u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0)); + rc->generate_name = gen_name; + name_unit(u); + CuAssertStrEquals(tc, "Hodor", unit_getname(u)); + test_cleanup(); +} + CuSuite *get_unit_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -491,5 +509,6 @@ CuSuite *get_unit_suite(void) SUITE_ADD_TEST(suite, test_inside_building); SUITE_ADD_TEST(suite, test_limited_skills); SUITE_ADD_TEST(suite, test_renumber_unit); + SUITE_ADD_TEST(suite, test_name_unit); return suite; } diff --git a/src/lighthouse.c b/src/lighthouse.c index d962b9b76..09c9b7d11 100644 --- a/src/lighthouse.c +++ b/src/lighthouse.c @@ -14,7 +14,7 @@ #include #include -const attrib_type at_lighthouse = { +attrib_type at_lighthouse = { "lighthouse" /* Rest ist NULL; tempor�res, nicht alterndes Attribut */ }; diff --git a/src/lighthouse.h b/src/lighthouse.h index 518b05b5a..3bf970bf1 100644 --- a/src/lighthouse.h +++ b/src/lighthouse.h @@ -29,7 +29,7 @@ extern "C" { struct building; struct attrib; - extern const struct attrib_type at_lighthouse; + extern struct attrib_type at_lighthouse; /* leuchtturm */ bool check_leuchtturm(struct region *r, struct faction *f); void update_lighthouse(struct building *lh); diff --git a/src/move.c b/src/move.c index b6a908837..f1b2311f1 100644 --- a/src/move.c +++ b/src/move.c @@ -571,7 +571,7 @@ direction_t reldirection(const region * from, const region * to) return NODIRECTION; } -static void leave_trail(ship * sh, region * from, region_list * route) +void leave_trail(ship * sh, region * from, region_list * route) { region *r = from; @@ -595,7 +595,7 @@ static void leave_trail(ship * sh, region * from, region_list * route) a = a->next; } - if (a == NULL) { + if (a == NULL || a->type != &at_shiptrail) { a = a_add(&(r->attribs), a_new(&at_shiptrail)); td = (traveldir *)a->data.v; td->no = sh->no; diff --git a/src/move.h b/src/move.h index 6363fe2f9..14c040493 100644 --- a/src/move.h +++ b/src/move.h @@ -63,6 +63,8 @@ extern "C" { int enoughsailors(const struct ship *sh, int sumskill); bool canswim(struct unit *u); bool canfly(struct unit *u); + void leave_trail(struct ship *sh, struct region *from, + struct region_list *route); struct ship *move_ship(struct ship *sh, struct region *from, struct region *to, struct region_list *route); int walkingcapacity(const struct unit *u); diff --git a/src/move.test.c b/src/move.test.c index bc93ec124..6a2a0e7db 100644 --- a/src/move.test.c +++ b/src/move.test.c @@ -3,6 +3,7 @@ #include "move.h" #include "keyword.h" +#include "lighthouse.h" #include #include @@ -478,7 +479,7 @@ static void test_drifting_ships(CuTest *tc) { region *r1, *r2, *r3; terrain_type *t_ocean, *t_plain; ship_type *st_boat; - test_cleanup(); + test_setup(); t_ocean = test_create_terrain("ocean", SEA_REGION); t_plain = test_create_terrain("plain", LAND_REGION); r1 = test_create_region(0, 0, t_ocean); @@ -491,11 +492,41 @@ static void test_drifting_ships(CuTest *tc) { test_cleanup(); } +static void test_ship_leave_trail(CuTest *tc) { + ship *s1, *s2; + region *r1, *r2; + terrain_type *t_ocean; + ship_type *st_boat; + region_list *route = NULL; + + test_setup(); + t_ocean = test_create_terrain("ocean", SEA_REGION); + r1 = test_create_region(0, 0, t_ocean); + add_regionlist(&route, test_create_region(2, 0, t_ocean)); + add_regionlist(&route, r2 = test_create_region(1, 0, t_ocean)); + st_boat = test_create_shiptype("boat"); + s1 = test_create_ship(r1, st_boat); + s2 = test_create_ship(r1, st_boat); + leave_trail(s1, r1, route); + a_add(&r1->attribs, a_new(&at_lighthouse)); + leave_trail(s2, r1, route); + a_add(&r2->attribs, a_new(&at_lighthouse)); + CuAssertPtrEquals(tc, &at_shiptrail, (void *)r1->attribs->type); + CuAssertPtrEquals(tc, &at_shiptrail, (void *)r1->attribs->next->type); + CuAssertPtrEquals(tc, &at_lighthouse, (void *)r1->attribs->next->next->type); + CuAssertPtrEquals(tc, &at_shiptrail, (void *)r2->attribs->type); + CuAssertPtrEquals(tc, &at_shiptrail, (void *)r2->attribs->next->type); + CuAssertPtrEquals(tc, &at_lighthouse, (void *)r2->attribs->next->next->type); + free_regionlist(route); + test_cleanup(); +} + CuSuite *get_move_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_walkingcapacity); SUITE_ADD_TEST(suite, test_ship_not_allowed_in_coast); + SUITE_ADD_TEST(suite, test_ship_leave_trail); SUITE_ADD_TEST(suite, test_ship_allowed_without_harbormaster); SUITE_ADD_TEST(suite, test_ship_blocked_by_harbormaster); SUITE_ADD_TEST(suite, test_ship_has_harbormaster_contact); diff --git a/src/names.c b/src/names.c index 99c21a05e..cf1cdb910 100644 --- a/src/names.c +++ b/src/names.c @@ -221,11 +221,7 @@ const char *silbe3[SIL3] = { static void generic_name(unit * u) { - const char * name = rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL); - name = LOC(u->faction->locale, name); - if (name) { - unit_setname(u, name); - } + unit_setname(u, NULL); } static void dragon_name(unit * u) diff --git a/src/names.test.c b/src/names.test.c index f50937f17..8109fc2d4 100644 --- a/src/names.test.c +++ b/src/names.test.c @@ -24,7 +24,7 @@ static void test_names(CuTest * tc) locale_setstring(default_locale, "undead_postfix_0", "Kobolde"); CuAssertPtrNotNull(tc, foo = (race_name_func)get_function("nameundead")); rc->generate_name = foo; - race_namegen(rc, u); + rc->generate_name(u); CuAssertStrEquals(tc, "Graue Kobolde", u->_name); CuAssertPtrNotNull(tc, get_function("nameskeleton")); CuAssertPtrNotNull(tc, get_function("namezombie")); @@ -36,9 +36,31 @@ static void test_names(CuTest * tc) test_cleanup(); } +static void test_monster_names(CuTest *tc) { + unit *u; + race *rc; + + test_setup(); + register_names(); + default_locale = test_create_locale(); + locale_setstring(default_locale, "race::irongolem", "Eisengolem"); + locale_setstring(default_locale, "race::irongolem_p", "Eisengolems"); + rc = test_create_race("irongolem"); + u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0)); + CuAssertPtrNotNull(tc, u->_name); + rc->generate_name = (race_name_func)get_function("namegeneric"); + rc->generate_name(u); + CuAssertPtrEquals(tc, 0, u->_name); + CuAssertStrEquals(tc, "Eisengolem", unit_getname(u)); + u->number = 2; + CuAssertStrEquals(tc, "Eisengolems", unit_getname(u)); + test_cleanup(); +} + CuSuite *get_names_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_names); + SUITE_ADD_TEST(suite, test_monster_names); return suite; } diff --git a/src/study.c b/src/study.c index 89be92bbd..3edde20a1 100644 --- a/src/study.c +++ b/src/study.c @@ -53,6 +53,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include + /* libc includes */ #include #include @@ -216,24 +218,11 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk, n = _min(n, nteaching); if (n != 0) { - int index = 0; - if (teach == NULL) { a = a_add(&student->attribs, a_new(&at_learning)); teach = (teaching_info *)a->data.v; } - else { - while (teach->teachers[index] && index != MAXTEACHERS) - ++index; - } - if (index < MAXTEACHERS) - teach->teachers[index++] = teacher; - if (index < MAXTEACHERS) { - teach->teachers[index] = NULL; - } - else { - log_error("MAXTEACHERS=%d is too low for student %s, teacher %s", MAXTEACHERS, unitname(student), unitname(teacher)); - } + ql_push(&teach->teachers, teacher); teach->value += n; if (student->building && teacher->building == student->building) { @@ -717,7 +706,7 @@ int study_cmd(unit * u, order * ord) a = a_add(&u->attribs, a_new(&at_learning)); teach = (teaching_info *)a->data.v; assert(teach); - teach->teachers[0] = 0; + teach->teachers = NULL; } if (money > 0) { use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, money); @@ -766,9 +755,9 @@ int study_cmd(unit * u, order * ord) learn_skill(u, sk, days); if (a != NULL) { - int index = 0; - while (teach->teachers[index] && index != MAXTEACHERS) { - unit *teacher = teach->teachers[index++]; + ql_iter qli = qli_init(&teach->teachers); + while (qli_more(qli)) { + unit *teacher = (unit *)qli_next(&qli); if (teacher->faction != u->faction) { bool feedback = alliedunit(u, teacher->faction, HELP_GUARD); if (feedback) { diff --git a/src/study.h b/src/study.h index 9d053dd5e..8067bc9bd 100644 --- a/src/study.h +++ b/src/study.h @@ -27,6 +27,7 @@ extern "C" { #endif struct unit; + struct quicklist; int teach_cmd(struct unit *u, struct order *ord); int study_cmd(struct unit *u, struct order *ord); @@ -45,10 +46,9 @@ extern "C" { void demon_skillchange(struct unit *u); -#define MAXTEACHERS 64 #define TEACHNUMBER 10 typedef struct teaching_info { - struct unit *teachers[MAXTEACHERS]; + struct quicklist *teachers; int value; } teaching_info; diff --git a/src/study.test.c b/src/study.test.c index 83628a123..d82c61690 100644 --- a/src/study.test.c +++ b/src/study.test.c @@ -2,6 +2,7 @@ #include "study.h" +#include #include #include #include @@ -10,15 +11,18 @@ #include #include #include +#include #include #include #include #include #include +#include +#include + #include -#include #define MAXLOG 4 typedef struct log_entry { @@ -511,6 +515,7 @@ static void test_teach_one_to_many(CuTest *tc) { static void test_teach_many_to_one(CuTest *tc) { unit *u, *u1, *u2; + test_setup(); init_resources(); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); @@ -533,6 +538,47 @@ static void test_teach_many_to_one(CuTest *tc) { test_cleanup(); } +static void test_teach_message(CuTest *tc) { + unit *u, *u1, *u2; + attrib *a; + ally *al; + teaching_info *teach; + + test_setup(); + init_resources(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + scale_number(u, 20); + u->thisorder = create_order(K_STUDY, u->faction->locale, "CROSSBOW"); + u1 = test_create_unit(test_create_faction(0), u->region); + set_level(u1, SK_CROSSBOW, TEACHDIFFERENCE); + u1->thisorder = create_order(K_TEACH, u->faction->locale, itoa36(u->no)); + u2 = test_create_unit(test_create_faction(0), u->region); + al = ally_add(&u->faction->allies, u2->faction); + al->status = HELP_GUARD; + set_level(u2, SK_CROSSBOW, TEACHDIFFERENCE); + u2->thisorder = create_order(K_TEACH, u->faction->locale, itoa36(u->no)); + CuAssertTrue(tc, !alliedunit(u, u1->faction, HELP_GUARD)); + CuAssertTrue(tc, alliedunit(u, u2->faction, HELP_GUARD)); + teach_cmd(u1, u1->thisorder); + teach_cmd(u2, u2->thisorder); + a = a_find(u->attribs, &at_learning); + CuAssertPtrNotNull(tc, a); + CuAssertPtrNotNull(tc, a->data.v); + teach = (teaching_info *)a->data.v; + CuAssertPtrNotNull(tc, teach->teachers); + CuAssertIntEquals(tc, 600, teach->value); + CuAssertIntEquals(tc, 2, ql_length(teach->teachers)); + CuAssertPtrEquals(tc, u1, ql_get(teach->teachers, 0)); + CuAssertPtrEquals(tc, u2, ql_get(teach->teachers, 1)); + study_cmd(u, u->thisorder); + CuAssertPtrEquals(tc, NULL, test_find_messagetype(u1->faction->msgs, "teach_teacher")); + CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "teach_teacher")); + CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "teach_student")); + a = a_find(u->attribs, &at_learning); + CuAssertPtrEquals(tc, NULL, a); + test_cleanup(); +} + static void test_teach_many_to_many(CuTest *tc) { unit *s1, *s2, *t1, *t2; region *r; @@ -583,6 +629,7 @@ CuSuite *get_study_suite(void) SUITE_ADD_TEST(suite, test_teach_one_to_many); SUITE_ADD_TEST(suite, test_teach_many_to_one); SUITE_ADD_TEST(suite, test_teach_many_to_many); + SUITE_ADD_TEST(suite, test_teach_message); SUITE_ADD_TEST(suite, test_teach_two_skills); SUITE_ADD_TEST(suite, test_learn_skill_single); SUITE_ADD_TEST(suite, test_learn_skill_multi);