diff --git a/res/core/messages.xml b/res/core/messages.xml
index 766cd481c..d40efb9ac 100644
--- a/res/core/messages.xml
+++ b/res/core/messages.xml
@@ -5291,6 +5291,7 @@
+
diff --git a/res/translations/messages.de.po b/res/translations/messages.de.po
index a1d30c85c..776a1e207 100644
--- a/res/translations/messages.de.po
+++ b/res/translations/messages.de.po
@@ -2370,7 +2370,7 @@ msgid "sp_confusion_effect_0"
msgstr "\"$unit($mage) stimmt einen seltsamen Gesang an. Ein plötzlicher Tumult entsteht, der sich jedoch schnell wieder legt.\""
msgid "pest"
-msgstr "\"Hier wütete die Pest, und $int($dead) Bauern starben.\""
+msgstr "\"Hier wütete die Pest, und $int($dead) $resource($peasants,$dead) $if($eq($dead,1), \"starb\", \"starben\").\""
msgid "wormhole_exit"
msgstr "\"$unit($unit) reist durch ein Wurmloch nach $region($region).\""
diff --git a/res/translations/messages.en.po b/res/translations/messages.en.po
index 037b50d4d..9621b3d73 100644
--- a/res/translations/messages.en.po
+++ b/res/translations/messages.en.po
@@ -2370,7 +2370,7 @@ msgid "sp_confusion_effect_0"
msgstr "\"$unit($mage) intones a mysterious chant. There is a sudden hubbub, but order is restored quickly.\""
msgid "pest"
-msgstr "\"The region is visited by the plague and $int($dead) peasants died.\""
+msgstr "\"The region is visited by the plague and $int($dead) $resource($$peasants,$dead) died.\""
msgid "wormhole_exit"
msgstr "\"$unit($unit) travels through a wormhole to $region($region).\""
diff --git a/res/translations/strings.de.po b/res/translations/strings.de.po
index 68f126335..e6931c344 100644
--- a/res/translations/strings.de.po
+++ b/res/translations/strings.de.po
@@ -571,7 +571,7 @@ msgid "balloon"
msgstr "Ballon"
msgid "nr_schemes_template"
-msgstr "Schemen der Regionen {0} sind erkennbar."
+msgstr "Schemen von {0} sind erkennbar."
msgid "list_two"
msgstr "{0} und {1}"
diff --git a/scripts/tests/e2/insects.lua b/scripts/tests/e2/insects.lua
index 1898e215c..f5b8a3213 100644
--- a/scripts/tests/e2/insects.lua
+++ b/scripts/tests/e2/insects.lua
@@ -85,3 +85,30 @@ function test_recruit_in_desert()
assert_equal('winter', get_season(get_turn()))
assert_equal(2, u.number)
end
+
+function test_ride_through_mountain()
+ local r1 = region.create(1, 0, "plain")
+ local r2 = region.create(2, 0, "mountain")
+ local r3 = region.create(3, 0, "plain")
+ local f = faction.create("insect")
+ local u = unit.create(f, r1, 1)
+ u.name="Hercules"
+ u:add_order('NACH O O')
+ u:add_item('horse', 1)
+ u:set_skill('riding', 1, true)
+ process_orders()
+ assert_equal(r3, u.region)
+end
+
+function test_ride_from_mountain()
+ local r1 = region.create(1, 0, "mountain")
+ local r2 = region.create(2, 0, "plain")
+ local r3 = region.create(3, 0, "plain")
+ local f = faction.create("insect")
+ local u = unit.create(f, r1, 1)
+ u:add_order('NACH O O')
+ u:add_item('horse', 1)
+ u:set_skill('riding', 1, true)
+ process_orders()
+ assert_equal(r2, u.region)
+end
diff --git a/src/laws.c b/src/laws.c
index 7f78ac04b..50d364660 100644
--- a/src/laws.c
+++ b/src/laws.c
@@ -2181,6 +2181,21 @@ int email_cmd(unit * u, struct order *ord)
return 0;
}
+bool password_wellformed(const char *password)
+{
+ unsigned char *c = (unsigned char *)password;
+ int i;
+ if (!password || password[0]=='\0') {
+ return false;
+ }
+ for (i = 0; c[i] && i != PASSWORD_MAXSIZE; ++i) {
+ if (!isalnum(c[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
int password_cmd(unit * u, struct order *ord)
{
char pwbuf[PASSWORD_MAXSIZE + 1];
@@ -2194,19 +2209,11 @@ int password_cmd(unit * u, struct order *ord)
pwbuf[PASSWORD_MAXSIZE - 1] = '\0';
}
- if (s && *s) {
- unsigned char *c = (unsigned char *)pwbuf;
- int i, r = 0;
-
- for (i = 0; c[i] && i != PASSWORD_MAXSIZE; ++i) {
- if (!isalnum(c[i])) {
- c[i] = 'X';
- ++r;
- }
- }
- if (r != 0) {
+ if (!s || !password_wellformed(s)) {
+ if (s) {
cmistake(u, ord, 283, MSG_EVENT);
}
+ password_generate(pwbuf, PASSWORD_MAXSIZE);
}
faction_setpassword(u->faction, password_hash(pwbuf, PASSWORD_DEFAULT));
ADDMSG(&u->faction->msgs, msg_message("changepasswd", "value", pwbuf));
diff --git a/src/laws.h b/src/laws.h
index 4924a5f6e..a49848ac9 100755
--- a/src/laws.h
+++ b/src/laws.h
@@ -48,6 +48,7 @@ extern "C" {
void sinkships(struct region * r);
void do_enter(struct region *r, bool is_final_attempt);
bool long_order_allowed(const struct unit *u);
+ bool password_wellformed(const char *password);
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 5dff45a92..8b92629b2 100644
--- a/src/laws.test.c
+++ b/src/laws.test.c
@@ -49,37 +49,6 @@ static void test_new_building_can_be_renamed(CuTest * tc)
test_teardown();
}
-static void test_password_cmd(CuTest * tc)
-{
- unit *u;
- faction * f;
- test_setup();
- u = test_create_unit(f = test_create_faction(NULL), test_create_plain(0, 0));
-
- u->thisorder = create_order(K_PASSWORD, f->locale, "abcdefgh");
- password_cmd(u, u->thisorder);
- CuAssertPtrNotNull(tc, faction_getpassword(f));
- CuAssertTrue(tc, checkpasswd(f, "abcdefgh"));
- CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd"));
- free_order(u->thisorder);
-
- u->thisorder = create_order(K_PASSWORD, f->locale, "abc*de*");
- password_cmd(u, u->thisorder);
- CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error283"));
- CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd"));
- CuAssertTrue(tc, !checkpasswd(f, "abc*de*"));
- CuAssertTrue(tc, checkpasswd(f, "abcXdeX"));
- free_order(u->thisorder);
-
- u->thisorder = create_order(K_PASSWORD, f->locale, "1234567890123456789012345678901234567890");
- password_cmd(u, u->thisorder);
- CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error321"));
- CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd"));
- CuAssertTrue(tc, checkpasswd(f, "1234567890123456789012345678901"));
-
- test_teardown();
-}
-
static void test_rename_building(CuTest * tc)
{
region *r;
@@ -1949,6 +1918,60 @@ static void test_long_order_on_ocean(CuTest *tc) {
test_teardown();
}
+static void test_password_cmd(CuTest *tc) {
+ unit *u;
+ message *msg;
+ faction * f;
+
+ CuAssertTrue(tc, password_wellformed("PASSword"));
+ CuAssertTrue(tc, password_wellformed("1234567"));
+ CuAssertTrue(tc, !password_wellformed("$password"));
+ CuAssertTrue(tc, !password_wellformed("no space"));
+
+ test_setup();
+ mt_create_error(283);
+ mt_create_error(321);
+ mt_create_va(mt_new("changepasswd", NULL), "value:string", MT_NEW_END);
+ u = test_create_unit(f = test_create_faction(NULL), test_create_plain(0, 0));
+ u->thisorder = create_order(K_PASSWORD, f->locale, "password1234", NULL);
+ password_cmd(u, u->thisorder);
+ CuAssertTrue(tc, checkpasswd(f, "password1234"));
+ CuAssertPtrNotNull(tc, msg = test_find_messagetype(f->msgs, "changepasswd"));
+ free_order(u->thisorder);
+ test_clear_messages(f);
+
+ u->thisorder = create_order(K_PASSWORD, f->locale, "bad-password", NULL);
+ password_cmd(u, u->thisorder);
+ CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error283"));
+ CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd"));
+ CuAssertTrue(tc, !checkpasswd(f, "password1234"));
+ free_order(u->thisorder);
+ test_clear_messages(f);
+
+ u->thisorder = create_order(K_PASSWORD, f->locale, "''", NULL);
+ password_cmd(u, u->thisorder);
+ CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error283"));
+ CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd"));
+ free_order(u->thisorder);
+ test_clear_messages(f);
+
+ u->thisorder = create_order(K_PASSWORD, f->locale, NULL);
+ password_cmd(u, u->thisorder);
+ CuAssertTrue(tc, !checkpasswd(f, "password1234"));
+ CuAssertPtrEquals(tc, NULL, test_find_messagetype(f->msgs, "error283"));
+ CuAssertPtrNotNull(tc, msg = test_find_messagetype(f->msgs, "changepasswd"));
+ free_order(u->thisorder);
+ test_clear_messages(f);
+
+ u->thisorder = create_order(K_PASSWORD, f->locale, "1234567890123456789012345678901234567890");
+ password_cmd(u, u->thisorder);
+ CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error321"));
+ CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd"));
+ CuAssertTrue(tc, checkpasswd(f, "1234567890123456789012345678901"));
+
+ test_teardown();
+}
+
static void test_peasant_migration(CuTest *tc) {
region *r1, *r2;
int rmax;
diff --git a/src/randenc.c b/src/randenc.c
index 368a839e9..356c9c695 100644
--- a/src/randenc.c
+++ b/src/randenc.c
@@ -587,7 +587,8 @@ void plagues(region * r)
}
if (dead > 0) {
- ADDMSG(&r->msgs, msg_message("pest", "dead", dead));
+ ADDMSG(&r->msgs, msg_message("pest", "peasants dead",
+ get_resourcetype(R_PEASANT), dead));
deathcounts(r, dead);
rsetpeasants(r, peasants - dead);
}