diff --git a/.gitignore b/.gitignore index 75ec9a227..98b1e8e0a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ ipch/ *~ *.pyc *.bak +*.swp bin/ build*/ *.log diff --git a/res/translations/strings.de.po b/res/translations/strings.de.po index 89875baf5..8720fc85d 100644 --- a/res/translations/strings.de.po +++ b/res/translations/strings.de.po @@ -6015,6 +6015,9 @@ msgstr "Eigentümer" msgid "nr_template" msgstr "Vorlage für den nächsten Zug:" +msgid "template_password_notice" +msgstr "Achtung: Hier muss das Passwort Deiner Partei eingefügt werden." + msgctxt "skill" msgid "espionage" msgstr "Spionage" diff --git a/res/translations/strings.en.po b/res/translations/strings.en.po index 8a5dcb30f..d096a77ae 100644 --- a/res/translations/strings.en.po +++ b/res/translations/strings.en.po @@ -5323,6 +5323,9 @@ msgstr "Owner" msgid "nr_template" msgstr "Template for the next turn:" +msgid "template_password_notice" +msgstr "Attention: Enter your faction's password here." + msgctxt "skill" msgid "espionage" msgstr "espionage" diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index 2aec0fc0f..70e1b61e4 100644 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -1182,3 +1182,21 @@ function test_cartmaking() assert_equal(1, u:get_item('cart')) assert_equal(5, u:get_item('log')) end + +function test_promote_after_recruit() + local f = faction.create('human') + local r1 = region.create(0, 0, 'plain') + local r2 = region.create(1, 0, 'plain') + local u1 = unit.create(f, r1, 1) + u1.name = 'Xolgrim' + local u2 = unit.create(f, r2, 55) + u2:add_order('REKRUTIERE 1') + u1:add_order('BEFOERDERE') + u1:add_item('money', 57) + u2:add_item('money', 150) + local fl = u1.flags + process_orders() + assert_equal(56, u2.number) + assert_equal(fl + 128, u1.flags) -- UFL_HERO + assert_equal(0, u1:get_item('money')) +end diff --git a/scripts/tests/e2/production.lua b/scripts/tests/e2/production.lua index 852d8f629..80d3447d2 100644 --- a/scripts/tests/e2/production.lua +++ b/scripts/tests/e2/production.lua @@ -108,7 +108,7 @@ end function test_build_boat_high_skill() local r = region.create(0, 0, "plain") - local f = faction.create("human", "skillz@example.com") + local f = faction.create("human") local u = unit.create(f, r, 1) u:set_skill("shipcraft", 5) -- humans get +1 u:add_item("log", 10) @@ -118,3 +118,86 @@ function test_build_boat_high_skill() assert_equal(5, u.ship.size) assert_equal(5, u:get_item('log')) end + +function test_work() + eressea.settings.set("rules.peasants.growth.factor", "0") + local r = region.create(0, 0, "plain") + r:set_resource('peasant', 1) + r:set_resource('tree', 0) + local f = faction.create("human") + local u = unit.create(f, r, 1) + u:add_order('ARBEITE') + r:set_resource('money', 0) + + process_orders() + assert_equal(10, u:get_item('money')) + assert_equal(1, r:get_resource('money')) + b = building.create(r, 'castle') + + b.size = 2 + r:set_resource('money', 0) + u:add_item('money', -u:get_item('money')) + process_orders() + assert_equal(10, u:get_item('money')) + assert_equal(1, r:get_resource('money')) + + b.size = 10 + r:set_resource('money', 0) + u:add_item('money', -u:get_item('money')) + process_orders() + assert_equal(11, u:get_item('money')) + assert_equal(2, r:get_resource('money')) + + b.size = 50 + r:set_resource('money', 0) + u:add_item('money', -u:get_item('money')) + process_orders() + assert_equal(12, u:get_item('money')) + assert_equal(3, r:get_resource('money')) + + r:set_resource('money', 0) + u:add_item('money', -u:get_item('money')) + b.size = 250 + process_orders() + assert_equal(13, u:get_item('money')) + assert_equal(4, r:get_resource('money')) + + r:set_resource('money', 0) + u:add_item('money', -u:get_item('money')) + b.size = 1250 + process_orders() + assert_equal(14, u:get_item('money')) + assert_equal(5, r:get_resource('money')) + + r:set_resource('money', 0) + u:add_item('money', -u:get_item('money')) + b.size = 6250 + process_orders() + assert_equal(15, u:get_item('money')) + assert_equal(6, r:get_resource('money')) +end + +function test_blessed_harvest() + eressea.settings.set("rules.peasants.growth.factor", "0") + local r = region.create(0, 0, "plain") + r:set_resource('peasant', 1) + r:set_resource('tree', 0) + local f = faction.create("human") + local u = unit.create(f, r, 1) + u:add_order('ARBEITE') + r:set_resource('money', 0) + r:add_curse('blessedharvest', nil, 2, 1, 1) -- duration, force, effect + + process_orders() + assert_equal(10, u:get_item('money')) -- only peasants benefit + assert_equal(2, r:get_resource('money')) -- peasants work +1 + + b = building.create(r, 'castle') + b.size = 6250 + r:set_resource('money', 0) + u:add_item('money', -u:get_item('money')) + assert_equal(1, r:get_curse('blessedharvest')) + process_orders() + assert_equal(15, u:get_item('money')) -- only peasants get +1 + assert_equal(7, r:get_resource('money')) -- peasants get +1 +end diff --git a/src/.report.c.swp b/src/.report.c.swp deleted file mode 100644 index c7bb683f3..000000000 Binary files a/src/.report.c.swp and /dev/null differ diff --git a/src/bind_region.c b/src/bind_region.c index 4a466b46f..414752cf6 100644 --- a/src/bind_region.c +++ b/src/bind_region.c @@ -699,6 +699,24 @@ static int tolua_distance(lua_State * L) return 1; } +static int tolua_region_add_curse(lua_State *L) { + region *r = (region *)tolua_tousertype(L, 1, NULL); + const char *name = tolua_tostring(L, 2, NULL); + const curse_type *ctype = ct_find(name); + if (ctype) { + unit *u = (unit *)tolua_tousertype(L, 3, NULL); + int duration = (int)tolua_tonumber(L, 4, 1); + double vigour = tolua_tonumber(L, 5, 0.0); + int effect = (int)tolua_tonumber(L, 6, vigour/2); + curse * c = create_curse(u, &r->attribs, ctype, vigour, duration, effect, 0); + if (c) { + lua_pushinteger(L, c->no); + return 1; + } + } + return 0; +} + static int tolua_region_get_curse(lua_State *L) { region *self = (region *)tolua_tousertype(L, 1, NULL); const char *name = tolua_tostring(L, 2, NULL); @@ -741,6 +759,7 @@ void tolua_region_open(lua_State * L) tolua_function(L, TOLUA_CAST "count_msg_type", tolua_region_count_msg_type); + tolua_function(L, TOLUA_CAST "add_curse", &tolua_region_add_curse); tolua_function(L, TOLUA_CAST "get_curse", &tolua_region_get_curse); tolua_function(L, TOLUA_CAST "has_attrib", &tolua_region_has_attrib); /* flags */ diff --git a/src/creport.c b/src/creport.c index 8f30fa50e..5720be4ce 100644 --- a/src/creport.c +++ b/src/creport.c @@ -1399,7 +1399,7 @@ static void cr_output_region(FILE * F, report_context * ctx, region * r) fprintf(F, "%d;Bauern\n", rpeasants(r)); fprintf(F, "%d;Pferde\n", rhorses(r)); - if (r->seen.mode >= seen_unit) { + if (r->seen.mode >= seen_travel) { if (rule_region_owners()) { faction *owner = region_get_owner(r); if (owner) { diff --git a/src/give.test.c b/src/give.test.c index c62973388..0aa99421a 100644 --- a/src/give.test.c +++ b/src/give.test.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ static void setup_give(struct give *env) { env->f1->locale = env->lang; } + config_set("rules.give.max_men", "-1"); /* success messages: */ mt_create_va(mt_new("receive_person", NULL), "unit:unit", "target:unit", "amount:int", MT_NEW_END); mt_create_va(mt_new("give_person", NULL), "unit:unit", "target:unit", "amount:int", MT_NEW_END); @@ -67,6 +69,8 @@ static void setup_give(struct give *env) { mt_create_va(mt_new("give", NULL), "unit:unit", "target:unit", "resource:resource", "amount:int", MT_NEW_END); mt_create_va(mt_new("give_peasants", NULL), "unit:unit", "resource:resource", "amount:int", MT_NEW_END); /* error messages: */ + mt_create_error(120); + mt_create_error(128); mt_create_error(129); mt_create_error(96); mt_create_error(10); @@ -84,21 +88,65 @@ static void setup_give(struct give *env) { static void test_give_unit(CuTest * tc) { struct give env = { 0 }; + test_setup_ex(tc); env.f1 = test_create_faction(NULL); env.f2 = test_create_faction(NULL); setup_give(&env); + + CuAssertIntEquals(tc, 1, env.f1->num_units); + CuAssertIntEquals(tc, 1, env.f2->num_units); + join_group(env.src, "group"); + config_set("rules.give.max_men", "0"); give_unit(env.src, env.dst, NULL); CuAssertPtrEquals(tc, env.f1, env.src->faction); CuAssertIntEquals(tc, 0, env.f2->newbies); + config_set("rules.give.max_men", "-1"); give_unit(env.src, env.dst, NULL); CuAssertPtrEquals(tc, env.f2, env.src->faction); + CuAssertPtrEquals(tc, NULL, get_group(env.src)); CuAssertIntEquals(tc, 1, env.f2->newbies); CuAssertPtrEquals(tc, NULL, env.f1->units); CuAssertPtrNotNull(tc, test_find_messagetype(env.f1->msgs, "give_person")); CuAssertPtrNotNull(tc, test_find_messagetype(env.f2->msgs, "receive_person")); + + test_teardown(); +} + +static void test_give_unit_humans(CuTest * tc) { + struct give env = { 0 }; + race *rc; + + test_setup_ex(tc); + env.f1 = test_create_faction(test_create_race("elf")); + env.f2 = test_create_faction(rc = test_create_race("human")); + rc->flags |= RCF_MIGRANTS; + setup_give(&env); + + give_unit(env.src, env.dst, NULL); + CuAssertPtrNotNull(tc, test_find_messagetype(env.f1->msgs, "error128")); + CuAssertIntEquals(tc, 0, env.f2->newbies); + + scale_number(env.dst, 57); + CuAssertIntEquals(tc, 1, count_maxmigrants(env.f2)); + give_unit(env.src, env.dst, NULL); + CuAssertIntEquals(tc, 1, env.f2->newbies); + test_teardown(); +} + +static void test_give_unit_other_race(CuTest * tc) { + struct give env = { 0 }; + test_setup_ex(tc); + env.f1 = test_create_faction(test_create_race("elf")); + env.f2 = test_create_faction(test_create_race("orc")); + setup_give(&env); + scale_number(env.dst, 57); + CuAssertIntEquals(tc, 0, count_maxmigrants(env.f2)); + give_unit(env.src, env.dst, NULL); + CuAssertIntEquals(tc, 0, env.f2->newbies); + CuAssertPtrNotNull(tc, test_find_messagetype(env.f1->msgs, "error120")); test_teardown(); } @@ -108,9 +156,8 @@ static void test_give_unit_limits(CuTest * tc) { env.f1 = test_create_faction(NULL); env.f2 = test_create_faction(NULL); setup_give(&env); - CuAssertIntEquals(tc, 1, env.f1->num_units); - CuAssertIntEquals(tc, 1, env.f2->num_units); config_set("rules.limit.faction", "1"); + give_unit(env.src, env.dst, NULL); CuAssertPtrEquals(tc, env.f1, env.src->faction); CuAssertIntEquals(tc, 0, env.f2->newbies); @@ -497,6 +544,8 @@ CuSuite *get_give_suite(void) SUITE_ADD_TEST(suite, test_give_men_requires_contact); SUITE_ADD_TEST(suite, test_give_men_not_to_self); SUITE_ADD_TEST(suite, test_give_unit); + SUITE_ADD_TEST(suite, test_give_unit_humans); + SUITE_ADD_TEST(suite, test_give_unit_other_race); SUITE_ADD_TEST(suite, test_give_unit_limits); SUITE_ADD_TEST(suite, test_give_unit_to_ocean); SUITE_ADD_TEST(suite, test_give_unit_to_peasants); diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 56b6a4ea1..b595bd902 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -205,10 +205,11 @@ static int unused_faction_id(void) return id; } -void faction_genpassword(faction *f) { - const char * password = itoa36(rng_int()); - faction_setpassword(f, password_hash(password, PASSWORD_DEFAULT)); - ADDMSG(&f->msgs, msg_message("changepasswd", "value", password)); +char *faction_genpassword(faction *f, char *buffer) { + password_generate(buffer, 8); + faction_setpassword(f, password_hash(buffer, PASSWORD_DEFAULT)); + ADDMSG(&f->msgs, msg_message("changepasswd", "value", buffer)); + return buffer; } faction *addfaction(const char *email, const char *password, diff --git a/src/kernel/faction.h b/src/kernel/faction.h index 438402286..cbe4c7008 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -150,7 +150,7 @@ extern "C" { const char *faction_getemail(const struct faction *self); void faction_setemail(struct faction *self, const char *email); - void faction_genpassword(struct faction *f); + char *faction_genpassword(struct faction *f, char *buffer); void faction_setpassword(struct faction *self, const char *pwhash); const char *faction_getpassword(const struct faction *f); bool valid_race(const struct faction *f, const struct race *rc); diff --git a/src/laws.c b/src/laws.c index 6696cc50f..3f2737dac 100644 --- a/src/laws.c +++ b/src/laws.c @@ -3840,6 +3840,10 @@ void init_processor(void) add_proc_region(p, do_force_leave, "kick non-allies out of buildings/ships"); } add_proc_region(p, economics, "Zerstoeren, Geben, Rekrutieren, Vergessen"); + + /* all recruitment must be finished before we can calculate + * promotion cost of ability */ + p += 10; add_proc_order(p, K_PROMOTION, promotion_cmd, 0, "Heldenbefoerderung"); p += 10; diff --git a/src/magic.c b/src/magic.c index e9e9cdd18..5273343cf 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2517,7 +2517,7 @@ static bool is_moving_ship(ship * sh) return false; } -#define MAX_PARAMETERS 32 +#define MAX_PARAMETERS 48 static castorder *cast_cmd(unit * u, order * ord) { char token[128]; diff --git a/src/report.c b/src/report.c index fd73f6369..79c154c50 100644 --- a/src/report.c +++ b/src/report.c @@ -1160,21 +1160,10 @@ void report_region(struct stream *out, const region * r, faction * f) static void statistics(struct stream *out, const region * r, const faction * f) { - const unit *u; - int number = 0, p = rpeasants(r); + int p = rpeasants(r); message *m; - item *itm, *items = NULL; char buf[4096]; - /* count */ - for (u = r->units; u; u = u->next) { - if (u->faction == f && !fval(u_race(u), RCF_INVISIBLE)) { - for (itm = u->items; itm; itm = itm->next) { - i_change(&items, itm->type, itm->number); - } - number += u->number; - } - } /* print */ m = msg_message("nr_stat_header", "region", r); nr_render(m, f->locale, buf, sizeof(buf), f); @@ -1210,6 +1199,21 @@ static void statistics(struct stream *out, const region * r, const faction * f) paragraph(out, buf, 2, 2, 0); msg_release(m); + if (r->land->ownership) { + m = msg_message("nr_stat_morale", "morale", region_get_morale(r)); + nr_render(m, f->locale, buf, sizeof(buf), f); + paragraph(out, buf, 2, 2, 0); + msg_release(m); + } + + } + + /* info about units */ + if (r->seen.mode >= seen_unit) { + int number; + item *itm, *items = NULL; + unit *u; + if (!markets_module()) { if (buildingtype_exists(r, bt_find("caravan"), true)) { m = msg_message("nr_stat_luxuries", "max", (p * 2) / TRADE_FRACTION); @@ -1222,28 +1226,28 @@ static void statistics(struct stream *out, const region * r, const faction * f) msg_release(m); } - if (r->land->ownership) { - m = msg_message("nr_stat_morale", "morale", region_get_morale(r)); - nr_render(m, f->locale, buf, sizeof(buf), f); - paragraph(out, buf, 2, 2, 0); - msg_release(m); + /* count */ + for (number = 0, u = r->units; u; u = u->next) { + if (u->faction == f && !fval(u_race(u), RCF_INVISIBLE)) { + for (itm = u->items; itm; itm = itm->next) { + i_change(&items, itm->type, itm->number); + } + number += u->number; + } } - - } - /* info about units */ - - m = msg_message("nr_stat_people", "max", number); - nr_render(m, f->locale, buf, sizeof(buf), f); - paragraph(out, buf, 2, 2, 0); - msg_release(m); - - for (itm = items; itm; itm = itm->next) { - sprintf(buf, "%s: %d", - LOC(f->locale, resourcename(itm->type->rtype, GR_PLURAL)), itm->number); + m = msg_message("nr_stat_people", "max", number); + nr_render(m, f->locale, buf, sizeof(buf), f); paragraph(out, buf, 2, 2, 0); + msg_release(m); + + for (itm = items; itm; itm = itm->next) { + sprintf(buf, "%s: %d", + LOC(f->locale, resourcename(itm->type->rtype, GR_PLURAL)), itm->number); + paragraph(out, buf, 2, 2, 0); + } + while (items) + i_free(i_remove(&items, items)); } - while (items) - i_free(i_remove(&items, items)); } @@ -1275,6 +1279,7 @@ report_template(const char *filename, report_context * ctx, const char *bom) stream strm = { 0 }, *out = &strm; char buf[4096]; sbstring sbs; + const char *password = "password"; if (F == NULL) { perror(filename); @@ -1286,12 +1291,17 @@ report_template(const char *filename, report_context * ctx, const char *bom) swrite(bom, 1, strlen(bom), out); } - newline(out); - rps_nowrap(out, LOC(lang, "nr_template")); - newline(out); - newline(out); + sprintf(buf, "; %s\n", LOC(lang, "nr_template")); + rps_nowrap(out, buf); - sprintf(buf, "%s %s \"password\"", LOC(lang, parameters[P_FACTION]), itoa36(f->no)); + if (ctx->password) { + password = ctx->password; + } + else { + sprintf(buf, "; %s\n", LOC(lang, "template_password_notice")); + rps_nowrap(out, buf); + } + sprintf(buf, "%s %s \"%s\"", LOC(lang, parameters[P_FACTION]), itoa36(f->no), password); rps_nowrap(out, buf); newline(out); newline(out); @@ -2163,10 +2173,13 @@ report_plaintext(const char *filename, report_context * ctx, newline(out); report_travelthru(out, r, f); } + newline(out); - if (wants_stats && r->seen.mode >= seen_unit) { - statistics(out, r, f); - newline(out); + if (wants_stats && r->seen.mode >= seen_travel) { + if (r->land || r->seen.mode >= seen_unit) { + newline(out); + statistics(out, r, f); + } } /* Nachrichten an REGION in der Region */ diff --git a/src/reports.c b/src/reports.c index 333787663..787a96f9f 100644 --- a/src/reports.c +++ b/src/reports.c @@ -71,6 +71,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "util/log.h" #include "util/macros.h" #include "util/path.h" +#include "util/password.h" #include "util/strings.h" #include "util/translation.h" #include @@ -1480,7 +1481,7 @@ void report_warnings(faction *f, int now) * this function may also update ctx->last and ctx->first for potential * lighthouses and travelthru reports */ -void prepare_report(report_context *ctx, faction *f) +void prepare_report(report_context *ctx, faction *f, const char *password) { region *r; static int config; @@ -1496,6 +1497,7 @@ void prepare_report(report_context *ctx, faction *f) rule_lighthouse_units = config_get_int("rules.lighthouse.unit_capacity", 0) != 0; } + ctx->password = password; ctx->f = f; ctx->report_time = time(NULL); ctx->addresses = NULL; @@ -1597,13 +1599,14 @@ int write_reports(faction * f) struct report_context ctx; const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 }; report_type *rtype; + char buffer[PASSWORD_MAXSIZE], *password = NULL; if (noreports) { return false; } if (f->lastorders == 0) { - faction_genpassword(f); + password = faction_genpassword(f, buffer); } - prepare_report(&ctx, f); + prepare_report(&ctx, f, password); get_addresses(&ctx); log_debug("Reports for %s", factionname(f)); for (rtype = report_types; rtype != NULL; rtype = rtype->next) { diff --git a/src/reports.h b/src/reports.h index 91af51bc2..00b94c8a7 100644 --- a/src/reports.h +++ b/src/reports.h @@ -77,9 +77,10 @@ extern "C" { struct region *first, *last; void *userdata; time_t report_time; + const char *password; } report_context; - void prepare_report(report_context *ctx, struct faction *f); + void prepare_report(report_context *ctx, struct faction *f, const char *password); void finish_reports(report_context *ctx); void get_addresses(report_context * ctx); diff --git a/src/reports.test.c b/src/reports.test.c index 0f5f850e9..aeeb0ff58 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -338,11 +338,11 @@ static void test_newbie_password_message(CuTest *tc) { f = test_create_faction(NULL); f->age = 5; f->flags = 0; - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertIntEquals(tc, 0, f->flags&FFL_PWMSG); CuAssertPtrEquals(tc, NULL, test_find_messagetype(f->msgs, "changepasswd")); f->age=2; - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertIntEquals(tc, FFL_PWMSG, f->flags&FFL_PWMSG); CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd")); finish_reports(&ctx); @@ -365,7 +365,7 @@ static void test_prepare_travelthru(CuTest *tc) { test_create_unit(f2, r3); u = test_create_unit(f, r1); travelthru_add(r2, u); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, r3, ctx.last); CuAssertPtrEquals(tc, f, ctx.f); @@ -375,7 +375,7 @@ static void test_prepare_travelthru(CuTest *tc) { finish_reports(&ctx); CuAssertIntEquals(tc, seen_none, r2->seen.mode); - prepare_report(&ctx, f2); + prepare_report(&ctx, f2, NULL); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); CuAssertIntEquals(tc, seen_neighbour, r2->seen.mode); CuAssertIntEquals(tc, seen_unit, r3->seen.mode); @@ -399,7 +399,7 @@ static void test_get_addresses(CuTest *tc) { test_create_unit(f, r); test_create_unit(f1, r); test_create_unit(f2, r); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); get_addresses(&ctx); @@ -427,7 +427,7 @@ static void test_get_addresses_fstealth(CuTest *tc) { u = test_create_unit(f1, r); set_factionstealth(u, f2); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); get_addresses(&ctx); @@ -470,7 +470,7 @@ static void test_get_addresses_travelthru(CuTest *tc) { u = test_create_unit(f4, r1); set_level(u, SK_STEALTH, 1); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); get_addresses(&ctx); @@ -516,14 +516,14 @@ void test_prepare_lighthouse_capacity(CuTest *tc) { u2->building = b; set_level(u2, SK_PERCEPTION, 3); CuAssertPtrEquals(tc, NULL, inside_building(u2)); - prepare_report(&ctx, u1->faction); + prepare_report(&ctx, u1->faction, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); CuAssertIntEquals(tc, seen_lighthouse, r2->seen.mode); finish_reports(&ctx); - prepare_report(&ctx, u2->faction); + prepare_report(&ctx, u2->faction, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); @@ -532,7 +532,7 @@ void test_prepare_lighthouse_capacity(CuTest *tc) { /* lighthouse capacity is # of units, not people: */ config_set_int("rules.lighthouse.unit_capacity", 1); - prepare_report(&ctx, u2->faction); + prepare_report(&ctx, u2->faction, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); @@ -567,7 +567,7 @@ static void test_prepare_lighthouse(CuTest *tc) { u = test_create_unit(f, r1); u->building = b; set_level(u, SK_PERCEPTION, 3); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); @@ -613,7 +613,7 @@ static void test_prepare_lighthouse_owners(CuTest *tc) u->building = b; region_set_owner(b->region, f, 0); CuAssertIntEquals(tc, 2, lighthouse_view_distance(b, NULL)); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); @@ -632,14 +632,14 @@ static void test_prepare_report(CuTest *tc) { f = test_create_faction(NULL); r = test_create_region(0, 0, NULL); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, NULL, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_none, r->seen.mode); finish_reports(&ctx); test_create_unit(f, r); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_unit, r->seen.mode); @@ -648,7 +648,7 @@ static void test_prepare_report(CuTest *tc) { r = test_create_region(2, 0, 0); CuAssertPtrEquals(tc, r, regions->next); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, regions, ctx.first); CuAssertPtrEquals(tc, r, ctx.last); CuAssertIntEquals(tc, seen_none, r->seen.mode); @@ -667,7 +667,7 @@ static void test_seen_neighbours(CuTest *tc) { r2 = test_create_region(1, 0, 0); test_create_unit(f, r1); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); @@ -694,7 +694,7 @@ static void test_seen_travelthru(CuTest *tc) { travelthru_add(r2, u); CuAssertPtrEquals(tc, r1, f->first); CuAssertPtrEquals(tc, r3, f->last); - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); @@ -772,7 +772,7 @@ static void test_report_far_vision(CuTest *tc) { CuAssertPtrEquals(tc, r1, f->first); CuAssertPtrEquals(tc, r2, f->last); report_context ctx; - prepare_report(&ctx, f); + prepare_report(&ctx, f, NULL); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); diff --git a/src/util/parser.c b/src/util/parser.c index f0090fdf3..3d1ba250d 100644 --- a/src/util/parser.c +++ b/src/util/parser.c @@ -15,14 +15,14 @@ #define ESCAPE_CHAR '\\' #define MAXTOKENSIZE 8192 -typedef struct parser_state { +typedef struct parse_state { const char *current_token; - struct parser_state *next; + struct parse_state *next; void *data; void(*dtor)(void *); -} parser_state; +} parse_state; -static parser_state *states; +static parse_state *states; static int eatwhitespace_c(const char **str_p) { @@ -57,7 +57,7 @@ static int eatwhitespace_c(const char **str_p) void init_tokens_ex(const char *initstr, void *data, void (*dtor)(void *)) { if (states == NULL) { - states = calloc(1, sizeof(parser_state)); + states = calloc(1, sizeof(parse_state)); if (!states) abort(); } else if (states->dtor) { @@ -74,7 +74,7 @@ void init_tokens_str(const char *initstr) { void parser_pushstate(void) { - parser_state *new_state = calloc(1, sizeof(parser_state)); + parse_state *new_state = calloc(1, sizeof(parse_state)); if (!new_state) abort(); new_state->current_token = NULL; new_state->next = states; @@ -83,7 +83,7 @@ void parser_pushstate(void) void parser_popstate(void) { - parser_state *new_state = states->next; + parse_state *new_state = states->next; if (states->dtor) { states->dtor(states->data); } diff --git a/src/util/password.c b/src/util/password.c index aab16acee..79e21d8bc 100644 --- a/src/util/password.c +++ b/src/util/password.c @@ -42,3 +42,12 @@ int password_verify(const char * pwhash, const char * passwd) { } return (strcmp(passwd, pwhash) == 0) ? VERIFY_OK : VERIFY_FAIL; } + +void password_generate(char *password, size_t length) { + char salt[BCRYPT_HASHSIZE]; + + assert(BCRYPT_HASHSIZE - 7 > length); + bcrypt_gensalt(4, salt); + memcpy(password, salt + 7, length); + password[length] = 0; +} diff --git a/src/util/password.h b/src/util/password.h index faa2a0a85..05be88578 100644 --- a/src/util/password.h +++ b/src/util/password.h @@ -1,6 +1,7 @@ #pragma once #include +#include typedef enum cryptalgo_t { PASSWORD_PLAINTEXT, PASSWORD_BCRYPT @@ -16,3 +17,4 @@ extern int bcrypt_workfactor; int password_verify(const char *hash, const char *passwd); const char * password_hash(const char *passwd, cryptalgo_t algo); bool password_is_implemented(cryptalgo_t algo); +void password_generate(char *password, size_t length);