diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml
index d318f7d56..349892e4e 100644
--- a/res/core/de/strings.xml
+++ b/res/core/de/strings.xml
@@ -484,13 +484,13 @@
- Mallornbaum
- mallorn tree
+ Mallorn
+ mallorn
- Mallornbäume
- mallorn trees
+ Mallorn
+ mallorn
diff --git a/src/attributes/otherfaction.h b/src/attributes/otherfaction.h
index 8a6471658..a274bcd49 100644
--- a/src/attributes/otherfaction.h
+++ b/src/attributes/otherfaction.h
@@ -25,9 +25,9 @@ extern "C" {
struct attrib;
extern struct attrib_type at_otherfaction;
- extern struct faction *get_otherfaction(const struct unit *u);
- extern struct attrib *make_otherfaction(struct faction *f);
- extern struct faction *visible_faction(const struct faction *f,
+ struct faction *get_otherfaction(const struct unit *u);
+ struct attrib *make_otherfaction(struct faction *f);
+ struct faction *visible_faction(const struct faction *f,
const struct unit *u);
#ifdef __cplusplus
diff --git a/src/creport.c b/src/creport.c
index f5d0f27fd..d16f87f22 100644
--- a/src/creport.c
+++ b/src/creport.c
@@ -751,7 +751,7 @@ void cr_output_unit(stream *out, const region * r, const faction * f,
const char *pzTmp;
skill *sv;
item result[MAX_INVENTORY];
- const faction *fother, *fseen;
+ const faction *fother;
const char *prefix;
bool allied;
@@ -783,24 +783,27 @@ void cr_output_unit(stream *out, const region * r, const faction * f,
}
}
- fseen = u->faction;
fother = get_otherfaction(u);
allied = u->faction == f || alliedunit(u, f, HELP_FSTEALTH);
- if (fother && f != u->faction && !allied) {
- /* getarnt, keine eigene, und kein HELFE fuer uns: wir sehen den fake */
- fseen = fother;
+ if (allied) {
+ /* allies can tell that the unit is anonymous */
+ /* the true faction is visible to allies */
+ stream_printf(out, "%d;Partei\n", u->faction->no);
+ if (fother) {
+ stream_printf(out, "%d;Anderepartei\n", fother->no);
+ }
+ } else if (!fval(u, UFL_ANON_FACTION)) {
+ /* OBS: anonymity overrides everything */
+ /* we have no alliance, so we get duped */
+ stream_printf(out, "%d;Partei\n", (fother ? fother : u->faction)->no);
+ if (fother==f) {
+ /* sieht aus wie unsere, ist es aber nicht. */
+ stream_printf(out, "1;Verraeter\n");
+ }
}
- stream_printf(out, "%d;Partei\n", fseen->no);
- if (fother && fother!=fseen) {
- stream_printf(out, "%d;Anderepartei\n", fother->no);
- }
- if (fseen==f && fval(u, UFL_ANON_FACTION)) {
+ if (fval(u, UFL_ANON_FACTION)) {
sputs("1;Parteitarnung", out);
}
- if (!allied && fother == f) {
- /* sieht aus wie unsere, ist es aber nicht. */
- stream_printf(out, "1;Verraeter\n");
- }
prefix = raceprefix(u);
if (prefix) {
prefix = mkname("prefix", prefix);
@@ -1091,12 +1094,16 @@ static void cr_reportspell(FILE * F, spell * sp, int level, const struct locale
static char *cr_output_resource(char *buf, const resource_type *rtype,
const struct locale *loc, int amount, int level)
{
- const char * name;
+ const char *name, *tname;
assert(rtype);
name = resourcename(rtype, 1);
assert(name);
buf += sprintf(buf, "RESOURCE %u\n", hashstring(rtype->_name));
- buf += sprintf(buf, "\"%s\";type\n", translate(name, LOC(loc, rtype->_name)));
+ tname = LOC(loc, rtype->_name);
+ assert(tname);
+ tname = translate(name, tname);
+ assert(tname);
+ buf += sprintf(buf, "\"%s\";type\n", tname);
if (amount >= 0) {
if (level >= 0)
buf += sprintf(buf, "%d;skill\n", level);
diff --git a/src/creport.test.c b/src/creport.test.c
index a56d1d589..46e6e6967 100644
--- a/src/creport.test.c
+++ b/src/creport.test.c
@@ -50,11 +50,7 @@ static void test_cr_unit(CuTest *tc) {
test_cleanup();
}
-static void test_cr_resources(CuTest *tc) {
- stream strm;
- char line[1024];
- faction *f;
- region *r;
+static void setup_resources(void) {
struct locale *lang;
test_setup();
@@ -70,6 +66,19 @@ static void test_cr_resources(CuTest *tc) {
locale_setstring(lang, "tree_p", "Blumen");
locale_setstring(lang, "sapling", "Schoessling");
locale_setstring(lang, "sapling_p", "Schoesslinge");
+ locale_setstring(lang, "mallornsapling", "Mallornschoessling");
+ locale_setstring(lang, "mallornsapling_p", "Mallornschoesslinge");
+ locale_setstring(lang, "mallorntree", "Mallorn");
+ locale_setstring(lang, "mallorntree_p", "Mallorn");
+}
+
+static void test_cr_resources(CuTest *tc) {
+ stream strm;
+ char line[1024];
+ faction *f;
+ region *r;
+
+ setup_resources();
f = test_create_faction(0);
r = test_create_region(0, 0, 0);
@@ -88,6 +97,20 @@ static void test_cr_resources(CuTest *tc) {
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
CuAssertStrEquals(tc, "2;Schoesslinge", line);
+ CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
+ CuAssertIntEquals(tc, 0, memcmp(line, "RESOURCE ", 9));
+ CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
+ CuAssertStrEquals(tc, "\"Schoesslinge\";type", line);
+ CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
+ CuAssertStrEquals(tc, "2;number", line);
+
+ CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
+ CuAssertIntEquals(tc, 0, memcmp(line, "RESOURCE ", 9));
+ CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
+ CuAssertStrEquals(tc, "\"Blumen\";type", line);
+ CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
+ CuAssertStrEquals(tc, "3;number", line);
+
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
CuAssertIntEquals(tc, 0, memcmp(line, "RESOURCE ", 9));
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
@@ -109,17 +132,49 @@ static void test_cr_resources(CuTest *tc) {
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
CuAssertStrEquals(tc, "1;number", line);
+ mstream_done(&strm);
+ test_cleanup();
+}
+
+static void test_cr_mallorn(CuTest *tc) {
+ stream strm;
+ char line[1024];
+ faction *f;
+ region *r;
+
+ setup_resources();
+
+ f = test_create_faction(0);
+ r = test_create_region(0, 0, 0);
+ r->land->horses = 1;
+ r->land->peasants = 200;
+ r->land->money = 300;
+ r->flags |= RF_MALLORN;
+ rsettrees(r, 0, 1);
+ rsettrees(r, 1, 2);
+ rsettrees(r, 2, 3);
+
+ mstream_init(&strm);
+ cr_output_resources(&strm, f, r, false);
+ strm.api->rewind(strm.handle);
+ CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
+ CuAssertStrEquals(tc, "3;Baeume", line);
+ CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
+ CuAssertStrEquals(tc, "2;Schoesslinge", line);
+ CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
+ CuAssertStrEquals(tc, "1;Mallorn", line);
+
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
CuAssertIntEquals(tc, 0, memcmp(line, "RESOURCE ", 9));
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
- CuAssertStrEquals(tc, "\"Schoesslinge\";type", line);
+ CuAssertStrEquals(tc, "\"Mallornschoesslinge\";type", line);
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
CuAssertStrEquals(tc, "2;number", line);
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
CuAssertIntEquals(tc, 0, memcmp(line, "RESOURCE ", 9));
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
- CuAssertStrEquals(tc, "\"Blumen\";type", line);
+ CuAssertStrEquals(tc, "\"Mallorn\";type", line);
CuAssertIntEquals(tc, 0, strm.api->readln(strm.handle, line, sizeof(line)));
CuAssertStrEquals(tc, "3;number", line);
@@ -130,10 +185,12 @@ static void test_cr_resources(CuTest *tc) {
static int cr_get_int(stream *strm, const char *match, int def)
{
char line[1024];
+ size_t len = strlen(match);
strm->api->rewind(strm->handle);
while (strm->api->readln(strm->handle, line, sizeof(line))==0) {
- if (strstr(line, match)) {
+ const char * pos = strstr(line, match);
+ if (pos && pos[len]=='\0') {
return atoi(line);
}
}
@@ -153,30 +210,69 @@ static void test_cr_factionstealth(CuTest *tc) {
r = test_create_region(0, 0, 0);
u = test_create_unit(f1, r);
+ /* report to ourselves */
mstream_init(&strm);
cr_output_unit(&strm, u->region, f1, u, seen_unit);
CuAssertIntEquals(tc, f1->no, cr_get_int(&strm, ";Partei", -1));
CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Anderepartei", -1));
CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Verraeter", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Parteitarnung", -1));
mstream_done(&strm);
+ /* ... also when we are anonymous */
+ u->flags |= UFL_ANON_FACTION;
+ mstream_init(&strm);
+ cr_output_unit(&strm, u->region, f1, u, seen_unit);
+ CuAssertIntEquals(tc, f1->no, cr_get_int(&strm, ";Partei", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Anderepartei", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Verraeter", -1));
+ CuAssertIntEquals(tc, 1, cr_get_int(&strm, ";Parteitarnung", -1));
+ u->flags &= ~UFL_ANON_FACTION;
+ mstream_done(&strm);
+
+ /* we see that our unit is cloaked */
set_factionstealth(u, f2);
CuAssertPtrNotNull(tc, u->attribs);
-
mstream_init(&strm);
cr_output_unit(&strm, u->region, f1, u, seen_unit);
CuAssertIntEquals(tc, f1->no, cr_get_int(&strm, ";Partei", -1));
CuAssertIntEquals(tc, f2->no, cr_get_int(&strm, ";Anderepartei", -1));
CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Verraeter", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Parteitarnung", -1));
mstream_done(&strm);
+ /* ... also when we are anonymous */
+ u->flags |= UFL_ANON_FACTION;
+ mstream_init(&strm);
+ cr_output_unit(&strm, u->region, f1, u, seen_unit);
+ CuAssertIntEquals(tc, f1->no, cr_get_int(&strm, ";Partei", -1));
+ CuAssertIntEquals(tc, f2->no, cr_get_int(&strm, ";Anderepartei", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Verraeter", -1));
+ CuAssertIntEquals(tc, 1, cr_get_int(&strm, ";Parteitarnung", -1));
+ u->flags &= ~UFL_ANON_FACTION;
+ mstream_done(&strm);
+
+ /* we can tell that someone is presenting as us */
mstream_init(&strm);
cr_output_unit(&strm, u->region, f2, u, seen_unit);
CuAssertIntEquals(tc, f2->no, cr_get_int(&strm, ";Partei", -1));
CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Anderepartei", -1));
CuAssertIntEquals(tc, 1, cr_get_int(&strm, ";Verraeter", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Parteitarnung", -1));
mstream_done(&strm);
+ /* ... but not if they are anonymous */
+ u->flags |= UFL_ANON_FACTION;
+ mstream_init(&strm);
+ cr_output_unit(&strm, u->region, f2, u, seen_unit);
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Partei", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Anderepartei", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Verraeter", -1));
+ CuAssertIntEquals(tc, 1, cr_get_int(&strm, ";Parteitarnung", -1));
+ u->flags &= ~UFL_ANON_FACTION;
+ mstream_done(&strm);
+
+ /* we see the same thing as them when we are an ally */
al = ally_add(&f1->allies, f2);
al->status = HELP_FSTEALTH;
mstream_init(&strm);
@@ -184,6 +280,18 @@ static void test_cr_factionstealth(CuTest *tc) {
CuAssertIntEquals(tc, f1->no, cr_get_int(&strm, ";Partei", -1));
CuAssertIntEquals(tc, f2->no, cr_get_int(&strm, ";Anderepartei", -1));
CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Verraeter", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Parteitarnung", -1));
+ mstream_done(&strm);
+
+ /* ... also when they are anonymous */
+ u->flags |= UFL_ANON_FACTION;
+ mstream_init(&strm);
+ cr_output_unit(&strm, u->region, f2, u, seen_unit);
+ CuAssertIntEquals(tc, f1->no, cr_get_int(&strm, ";Partei", -1));
+ CuAssertIntEquals(tc, f2->no, cr_get_int(&strm, ";Anderepartei", -1));
+ CuAssertIntEquals(tc, -1, cr_get_int(&strm, ";Verraeter", -1));
+ CuAssertIntEquals(tc, 1, cr_get_int(&strm, ";Parteitarnung", -1));
+ u->flags &= ~UFL_ANON_FACTION;
mstream_done(&strm);
test_cleanup();
@@ -194,6 +302,7 @@ CuSuite *get_creport_suite(void)
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_cr_unit);
SUITE_ADD_TEST(suite, test_cr_resources);
+ SUITE_ADD_TEST(suite, test_cr_mallorn);
SUITE_ADD_TEST(suite, test_cr_factionstealth);
return suite;
}
diff --git a/src/give.c b/src/give.c
index 2de8ccf72..0f1c56c39 100644
--- a/src/give.c
+++ b/src/give.c
@@ -132,12 +132,12 @@ static void add_give_person(unit * u, unit * u2, int given,
else if (u2->faction != u->faction) {
message *msg;
- msg = msg_message("give_person", "unit target resource amount",
+ msg = msg_message("give_person", "unit target amount",
u, u2, given);
add_message(&u->faction->msgs, msg);
msg_release(msg);
- msg = msg_message("receive_person", "unit target resource amount",
+ msg = msg_message("receive_person", "unit target amount",
u, u2, given);
add_message(&u2->faction->msgs, msg);
msg_release(msg);
diff --git a/src/reports.c b/src/reports.c
index aae3d3031..c23809a32 100644
--- a/src/reports.c
+++ b/src/reports.c
@@ -410,6 +410,20 @@ const faction * viewer, bool see_unit)
bool mallorn = fval(r, RF_MALLORN) != 0;
const resource_type *rtype;
+ if (saplings) {
+ if (n >= size)
+ return -1;
+ rtype = get_resourcetype(mallorn ? R_MALLORN_SAPLING : R_SAPLING);
+ report_resource(result + n, rtype, saplings, -1);
+ ++n;
+ }
+ if (trees) {
+ if (n >= size)
+ return -1;
+ rtype = get_resourcetype(mallorn ? R_MALLORN_TREE : R_TREE);
+ report_resource(result + n, rtype, trees, -1);
+ ++n;
+ }
if (money) {
if (n >= size)
return -1;
@@ -428,20 +442,6 @@ const faction * viewer, bool see_unit)
report_resource(result + n, get_resourcetype(R_HORSE), horses, -1);
++n;
}
- if (saplings) {
- if (n >= size)
- return -1;
- rtype = get_resourcetype(mallorn ? R_MALLORN_SAPLING : R_SAPLING);
- report_resource(result + n, rtype, saplings, -1);
- ++n;
- }
- if (trees) {
- if (n >= size)
- return -1;
- rtype = get_resourcetype(mallorn ? R_MALLORN_TREE : R_TREE);
- report_resource(result + n, rtype, trees, -1);
- ++n;
- }
}
if (see_unit) {
@@ -536,6 +536,10 @@ size_t size)
if (wrptr(&bufp, &size, result) != 0)
WARN_STATIC_BUFFER();
}
+ else {
+ bufp = STRLCPY(bufp, ", ", size);
+ bufp = STRLCPY(bufp, factionname(fv), size);
+ }
}
else {
bufp = STRLCPY(bufp, ", ", size);
diff --git a/src/reports.test.c b/src/reports.test.c
index c026041a9..976e9dfe1 100644
--- a/src/reports.test.c
+++ b/src/reports.test.c
@@ -7,6 +7,7 @@
#include "travelthru.h"
#include "keyword.h"
+#include
#include
#include
#include
@@ -20,10 +21,14 @@
#include
#include
+#include
#include
#include
#include
+#include
+#include
+
#include
#include
#include
@@ -153,14 +158,97 @@ static void test_sparagraph(CuTest *tc) {
freestrlist(sp);
}
-static void test_write_unit(CuTest *tc) {
+static void test_bufunit_fstealth(CuTest *tc) {
+ faction *f1, *f2;
+ region *r;
+ unit *u;
+ ally *al;
+ char buf[256];
+ struct locale *lang;
+
+ test_setup();
+ lang = get_or_create_locale("de");
+ locale_setstring(lang, "status_aggressive", "aggressive");
+ locale_setstring(lang, "anonymous", "anonymous");
+ f1 = test_create_faction(0);
+ f1->locale = lang;
+ f2 = test_create_faction(0);
+ f2->locale = lang;
+ r = test_create_region(0, 0, 0);
+ u = test_create_unit(f1, r);
+ faction_setname(f1, "UFO");
+ renumber_faction(f1, 1);
+ faction_setname(f2, "TWW");
+ renumber_faction(f2, 2);
+ unit_setname(u, "Hodor");
+ unit_setid(u, 1);
+ key_set(&u->attribs, 42, 42);
+
+ /* report to ourselves */
+ bufunit(f1, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressive.", buf);
+
+ /* ... also when we are anonymous */
+ u->flags |= UFL_ANON_FACTION;
+ bufunit(f1, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human, aggressive.", buf);
+ u->flags &= ~UFL_ANON_FACTION;
+
+ /* we see that our unit is cloaked */
+ set_factionstealth(u, f2);
+ CuAssertPtrNotNull(tc, u->attribs);
+ bufunit(f1, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), TWW (2), 1 human, aggressive.", buf);
+
+ /* ... also when we are anonymous */
+ u->flags |= UFL_ANON_FACTION;
+ bufunit(f1, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human, aggressive.", buf);
+ u->flags &= ~UFL_ANON_FACTION;
+
+ /* we can see that someone is presenting as us */
+ bufunit(f2, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), TWW (2), 1 human.", buf);
+
+ /* ... but not if they are anonymous */
+ u->flags |= UFL_ANON_FACTION;
+ bufunit(f2, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human.", buf);
+ u->flags &= ~UFL_ANON_FACTION;
+
+ /* we see the same thing as them when we are an ally */
+ al = ally_add(&f1->allies, f2);
+ al->status = HELP_FSTEALTH;
+ bufunit(f2, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), TWW (2) (UFO (1)), 1 human.", buf);
+
+ /* ... also when they are anonymous */
+ u->flags |= UFL_ANON_FACTION;
+ bufunit(f2, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human.", buf);
+ u->flags &= ~UFL_ANON_FACTION;
+
+ /* fstealth has no influence when we are allies, same results again */
+ set_factionstealth(u, NULL);
+ bufunit(f2, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), UFO (1), 1 human.", buf);
+
+ u->flags |= UFL_ANON_FACTION;
+ bufunit(f2, u, 0, seen_unit, buf, sizeof(buf));
+ CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human.", buf);
+ u->flags &= ~UFL_ANON_FACTION;
+
+ test_cleanup();
+}
+
+static void test_bufunit(CuTest *tc) {
unit *u;
faction *f;
race *rc;
struct locale *lang;
- char buffer[1024];
+ char buffer[256];
- test_cleanup();
+ test_setup();
rc = rc_get_or_create("human");
rc->bonus[SK_ALCHEMY] = 1;
lang = get_or_create_locale("de");
@@ -191,6 +279,7 @@ static void test_write_unit(CuTest *tc) {
f->locale = get_or_create_locale("de");
bufunit(f, u, 0, 0, buffer, sizeof(buffer));
CuAssertStrEquals(tc, "Hodor (1), UFO (1), 1 human.", buffer);
+
test_cleanup();
}
@@ -580,7 +669,8 @@ CuSuite *get_reports_suite(void)
SUITE_ADD_TEST(suite, test_seen_faction);
SUITE_ADD_TEST(suite, test_regionid);
SUITE_ADD_TEST(suite, test_sparagraph);
- SUITE_ADD_TEST(suite, test_write_unit);
+ SUITE_ADD_TEST(suite, test_bufunit);
+ SUITE_ADD_TEST(suite, test_bufunit_fstealth);
SUITE_ADD_TEST(suite, test_arg_resources);
return suite;
}
diff --git a/tests/runtests.bat b/tests/runtests.bat
index 41b5f8056..7a58e5762 100644
--- a/tests/runtests.bat
+++ b/tests/runtests.bat
@@ -3,6 +3,7 @@ IF EXIST ..\build-vs10 SET BUILD=..\build-vs10\eressea\Debug
IF EXIST ..\build-vs11 SET BUILD=..\build-vs11\eressea\Debug
IF EXIST ..\build-vs12 SET BUILD=..\build-vs12\eressea\Debug
IF EXIST ..\build-vs14 SET BUILD=..\build-vs14\eressea\Debug
+IF EXIST ..\build-vs15 SET BUILD=..\build-vs15\eressea\Debug
SET SERVER=%BUILD%\eressea.exe
%BUILD%\test_eressea.exe
%SERVER% ..\scripts\run-tests.lua
diff --git a/vs2017-build.bat b/vs2017-build.bat
new file mode 100644
index 000000000..7503153fe
--- /dev/null
+++ b/vs2017-build.bat
@@ -0,0 +1,13 @@
+@ECHO OFF
+SET VSVERSION=15
+SET SRCDIR=%CD%
+CD ..
+SET ERESSEA=%CD%
+
+CD %SRCDIR%
+IF exist build-vs%VSVERSION% goto HAVEDIR
+mkdir build-vs%VSVERSION%
+:HAVEDIR
+cd build-vs%VSVERSION%
+"%ProgramFiles%\CMake\bin\cmake.exe" -G "Visual Studio %VSVERSION%" -DCMAKE_PREFIX_PATH="%ProgramFiles(x86)%/Lua/5.1;%ERESSEA%/dependencies-win32" -DCMAKE_MODULE_PATH="%SRCDIR%/cmake/Modules" -DCMAKE_SUPPRESS_REGENERATION=TRUE ..
+PAUSE