From d288c74aaf59aeea7f02ca72e27d96d09d16f158 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Sun, 1 Feb 2015 19:14:06 +0100 Subject: [PATCH] fix stork message (mantis 2027), add tests --- res/core/messages.xml | 4 +-- src/laws.c | 21 ++++++++------- src/laws.h | 2 +- src/laws.test.c | 45 ++++++++++++++++++++++++++----- src/tests.c | 61 ++++++++++++++++++++++++++++++++++++++++++- src/tests.h | 7 +++++ 6 files changed, 120 insertions(+), 20 deletions(-) diff --git a/res/core/messages.xml b/res/core/messages.xml index 48a76b390..52dab404c 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -942,8 +942,8 @@ - "Die Region ist im Besitz von $faction($faction)." - "The region is owned by $faction($faction)." + " Die Region ist im Besitz von $faction($faction)." + " The region is owned by $faction($faction)." diff --git a/src/laws.c b/src/laws.c index 86f09bcd3..acb15e747 100755 --- a/src/laws.c +++ b/src/laws.c @@ -97,8 +97,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#include - /* chance that a peasant dies of starvation: */ #define PEASANT_STARVATION_CHANCE 0.9F /* Pferdevermehrung */ @@ -240,7 +238,7 @@ static void calculate_emigration(region * r) } for (i = 0; max_immigrants > 0 && i != MAXDIRECTIONS; i++) { - int dir = (turn + i) % MAXDIRECTIONS; + int dir = (turn + 1 + i) % MAXDIRECTIONS; region *rc = rconnect(r, (direction_t)dir); if (rc != NULL && fval(rc->terrain, LAND_REGION)) { @@ -265,7 +263,7 @@ static float peasant_growth_factor(void) } #ifdef SLOWLUCK -int peasant_luck_effect(int peasants, int luck, int maxp, float variance) { +int peasant_luck_effect(int peasants, int luck, int maxp, double variance) { int n, births=0; float factor = peasant_growth_factor(); for (n = peasants; n && luck; --n) { @@ -294,11 +292,15 @@ static float peasant_luck_factor(void) return get_param_flt(global.parameters, "rules.peasants.peasantluck.factor", PEASANTLUCK); } -int peasant_luck_effect(int peasants, int luck, int maxp, float variance) +int peasant_luck_effect(int peasants, int luck, int maxp, double variance) { int births = 0; - double mean = _min(luck, peasants) * peasant_luck_factor() - * peasant_growth_factor() * ((peasants / (float)maxp < .9) ? 1 : + double mean; + + if (luck == 0) return 0; + + mean = _min(luck, peasants) * peasant_luck_factor() + * peasant_growth_factor() * ((peasants / (double)maxp < .9) ? 1 : PEASANTFORCE); births = RAND_ROUND(normalvariate(mean, variance * mean)); @@ -330,9 +332,8 @@ static void peasants(region * r) } luck = peasant_luck_effect(peasants, luck, maxp, .5); -#ifdef STORCH_SPAM_BUG_2072 - ADDMSG(&r->msgs, msg_message("peasantluck_success", "births", luck)); -#endif + if (luck > 0) + ADDMSG(&r->msgs, msg_message("peasantluck_success", "births", luck)); peasants += births + luck; } diff --git a/src/laws.h b/src/laws.h index 3e9c44013..4f4188448 100755 --- a/src/laws.h +++ b/src/laws.h @@ -106,7 +106,7 @@ extern "C" { const struct unit *u, int modifier); int armedmen(const struct unit *u, bool siege_weapons); void force_leave(struct region *r); - int peasant_luck_effect(int peasants, int luck, int maxp, float variance); + int peasant_luck_effect(int peasants, int luck, int maxp, double variance); #ifdef __cplusplus } diff --git a/src/laws.test.c b/src/laws.test.c index 7524e6267..75c19a798 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include #include +#include #include #include #include @@ -457,7 +459,7 @@ struct pay_fixture { }; static double level_taxes(const building * b, int level) { - return b->size*level*2.0; + return b->size * level * 2.0; } static void setup_pay_cmd(struct pay_fixture *fix) { @@ -693,8 +695,7 @@ static void test_reserve_self(CuTest *tc) { } static void statistic_test(CuTest *tc, int peasants, int luck, int maxp, - float variance, int min_value, int max_value) -{ + double variance, int min_value, int max_value) { int effect, i; for (i = 0; i < 1000; ++i) { effect = peasant_luck_effect(peasants, luck, maxp, variance); @@ -703,19 +704,50 @@ static void statistic_test(CuTest *tc, int peasants, int luck, int maxp, } } -static void test_peasant_luck_effect(CuTest *tc) -{ +static void test_peasant_luck_effect(CuTest *tc) { + const char *plf = get_param(global.parameters, "rules.peasants.peasantluck.factor"); + const char *gf = get_param(global.parameters, "rules.peasants.growth.factor"); set_param(&global.parameters, "rules.peasants.peasantluck.factor", "10"); set_param(&global.parameters, "rules.peasants.growth.factor", "0.001"); + statistic_test(tc, 100, 0, 1000, 0, 0, 0); statistic_test(tc, 100, 2, 1000, 0, 1, 1); statistic_test(tc, 1000, 400, 1000, 0, (int)(400 * 10 * 0.001 * .75), (int)(400 * 10 * 0.001 * .75)); - statistic_test(tc, 1000, 1000, 2000, .5f, 1, 501); + statistic_test(tc, 1000, 1000, 2000, .5, 1, 501); set_param(&global.parameters, "rules.peasants.growth.factor", "1"); statistic_test(tc, 1000, 1000, 1000, 0, 501, 501); + + set_param(&global.parameters, "rules.peasants.peasantluck.factor", plf); + set_param(&global.parameters, "rules.peasants.growth.factor", gf); +} + +static void test_luck_message(CuTest *tc) { + region* r; + const message_type *msg_types[1]; + + test_cleanup(); + r = test_create_region(0, 0, NULL); + rsetpeasants(r, 1); + + msg_types[0] = register_msg("peasantluck_success", 1, "births:int"); + + demographics(); + + CuAssertPtrEquals_Msg(tc, "unexpected message", (void *)NULL, r->msgs); + + attrib *a = (attrib *)a_find(r->attribs, &at_peasantluck); + if (!a) + a = a_add(&r->attribs, a_new(&at_peasantluck)); + a->data.i += 10; + + demographics(); + + assert_messages(tc, r->msgs->begin, msg_types, 1, true, 0); + + test_cleanup(); } CuSuite *get_laws_suite(void) @@ -749,6 +781,7 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_force_leave_ships); SUITE_ADD_TEST(suite, test_force_leave_ships_on_ocean); SUITE_ADD_TEST(suite, test_peasant_luck_effect); + SUITE_ADD_TEST(suite, test_luck_message); return suite; } diff --git a/src/tests.c b/src/tests.c index 0d113229b..108cde2a4 100644 --- a/src/tests.c +++ b/src/tests.c @@ -20,6 +20,8 @@ #include #include +#include + #include #include #include @@ -35,7 +37,13 @@ struct race *test_create_race(const char *name) struct region *test_create_region(int x, int y, const terrain_type *terrain) { region *r = new_region(x, y, NULL, 0); - terraform_region(r, terrain ? terrain : get_or_create_terrain("plain")); + if (!terrain) { + terrain_type *t = get_or_create_terrain("plain"); + t->size = 1000; + fset(t, LAND_REGION); + terraform_region(r, t); + } else + terraform_region(r, terrain); rsettrees(r, 0, 0); rsettrees(r, 1, 0); rsettrees(r, 2, 0); @@ -213,3 +221,54 @@ const char * test_get_messagetype(const message *msg) { return name; } +const message_type *register_msg(const char *type, int n_param, ...) { + char **argv; + va_list args; + int i; + + va_start(args, n_param); + + argv = malloc(sizeof(char *) * (n_param + 1)); + for (i = 0; i < n_param; ++i) { + argv[i] = va_arg(args, char *); + } + argv[n_param] = 0; + va_end(args); + return mt_register(mt_new(type, (const char **)argv)); +} + +void assert_messages(struct CuTest * tc, struct mlist *msglist, const message_type **types, + int num_msgs, bool exact_match, ...) { + va_list args; + int found, argc; + struct message *msg; + bool match = true; + + va_start(args, exact_match); + + found = 0; + while (msglist) { + if (found >= num_msgs) { + if (exact_match) { + CuFail(tc, "too many messages"); + } else { + break; + } + } + msg = msglist->msg; + if (exact_match || match) + argc = va_arg(args, int); + + match = strcmp(types[argc]->name, msg->type->name) == 0; + if (match) + ++found; + else if (exact_match) + CuAssertStrEquals(tc, types[argc]->name, msg->type->name); + + msglist = msglist->next; + } + + CuAssertIntEquals_Msg(tc, "not enough messages", num_msgs, found); + + va_end(args); +} diff --git a/src/tests.h b/src/tests.h index b83beab40..e517a6fb7 100644 --- a/src/tests.h +++ b/src/tests.h @@ -15,11 +15,14 @@ extern "C" { struct ship; struct message; struct message_list; + struct mlist; struct item_type; struct building_type; struct ship_type; struct terrain_type; + struct CuTest; + void test_cleanup(void); struct terrain_type * test_create_terrain(const char * name, unsigned int flags); @@ -40,6 +43,10 @@ extern "C" { const char * test_get_messagetype(const struct message *msg); struct message * test_get_last_message(struct message_list *mlist); + const struct message_type *register_msg(const char *type, int n_param, ...); + void assert_messages(struct CuTest * tc, struct mlist *msglist, const struct message_type **types, + int num_msgs, bool exact_match, ...); + #ifdef __cplusplus } #endif