Merge branch 'master' of github.com:eressea/server

This commit is contained in:
Enno Rehling 2014-06-28 16:39:54 -07:00
commit 612dfea36f
10 changed files with 180 additions and 33 deletions

View File

@ -3,7 +3,7 @@
Version="10.0" Version="10.0"
VendorName="SlickEdit" VendorName="SlickEdit"
TemplateName="GNU C/C++" TemplateName="GNU C/C++"
WorkingDir="." WorkingDir=".."
BuildSystem="vsbuild"> BuildSystem="vsbuild">
<Config <Config
Name="Debug" Name="Debug"
@ -244,7 +244,9 @@
<F N="../src/util/base36.test.c"/> <F N="../src/util/base36.test.c"/>
<F N="../src/kernel/battle.test.c"/> <F N="../src/kernel/battle.test.c"/>
<F N="../src/util/bsdstring.test.c"/> <F N="../src/util/bsdstring.test.c"/>
<F N="../src/kernel/build.test.c"/>
<F N="../src/kernel/building.test.c"/> <F N="../src/kernel/building.test.c"/>
<F N="../src/kernel/config.test.c"/>
<F N="../src/kernel/curse.test.c"/> <F N="../src/kernel/curse.test.c"/>
<F N="../src/direction.test.c"/> <F N="../src/direction.test.c"/>
<F N="../src/economy.test.c"/> <F N="../src/economy.test.c"/>
@ -282,13 +284,15 @@
<Folder <Folder
Name="Other Files" Name="Other Files"
Filters=""> Filters="">
<F N="../tests/castles.lua"/>
<F N="../tests/config.lua"/> <F N="../tests/config.lua"/>
<F N="../src/game.pkg"/>
<F N="../tests/init.lua"/> <F N="../tests/init.lua"/>
<F N="../tests/locale.lua"/> <F N="../tests/locale.lua"/>
<F N="../tests/movement.lua"/>
<F N="../tests/regions.lua"/> <F N="../tests/regions.lua"/>
<F N="../tests/settings.lua"/> <F N="../tests/settings.lua"/>
<F N="../tests/ships.lua"/> <F N="../tests/ships.lua"/>
<F N="../tests/study.lua"/>
</Folder> </Folder>
</Files> </Files>
</Project> </Project>

View File

@ -1792,7 +1792,8 @@ int make_cmd(unit * u, struct order *ord)
if (pl && fval(pl, PFL_NOBUILD)) { if (pl && fval(pl, PFL_NOBUILD)) {
cmistake(u, ord, 94, MSG_PRODUCE); cmistake(u, ord, 94, MSG_PRODUCE);
} else { } else {
build_building(u, btype, m, ord); int id = getid();
build_building(u, btype, id, m, ord);
} }
} else if (itype != NULL) { } else if (itype != NULL) {
create_item(u, itype, m); create_item(u, itype, m);

View File

@ -1,6 +1,7 @@
project(kernel C) project(kernel C)
SET(_TEST_FILES SET(_TEST_FILES
build.test.c
config.test.c config.test.c
ship.test.c ship.test.c
spell.test.c spell.test.c

View File

@ -424,7 +424,7 @@ int build(unit * u, const construction * ctype, int completed, int want)
if (want <= 0) if (want <= 0)
return 0; return 0;
if (type == NULL) if (type == NULL)
return 0; return ENOMATERIALS;
if (type->improvement == NULL && completed == type->maxsize) if (type->improvement == NULL && completed == type->maxsize)
return ECOMPLETE; return ECOMPLETE;
if (type->btype != NULL) { if (type->btype != NULL) {
@ -616,7 +616,7 @@ message *msg_materials_required(unit * u, order * ord,
if (multi <= 0 || multi == INT_MAX) if (multi <= 0 || multi == INT_MAX)
multi = 1; multi = 1;
for (c = 0; ctype->materials[c].number; ++c) { for (c = 0; ctype && ctype->materials[c].number; ++c) {
resource *res = malloc(sizeof(resource)); resource *res = malloc(sizeof(resource));
res->number = multi * ctype->materials[c].number / ctype->reqsize; res->number = multi * ctype->materials[c].number / ctype->reqsize;
res->type = ctype->materials[c].rtype; res->type = ctype->materials[c].rtype;
@ -646,11 +646,11 @@ int maxbuild(const unit * u, const construction * cons)
/** old build routines */ /** old build routines */
void int
build_building(unit * u, const building_type * btype, int want, order * ord) build_building(unit * u, const building_type * btype, int id, int want, order * ord)
{ {
region *r = u->region; region *r = u->region;
int n = want, built = 0, id; int n = want, built = 0;
building *b = NULL; building *b = NULL;
/* einmalige Korrektur */ /* einmalige Korrektur */
const char *btname; const char *btname;
@ -659,9 +659,10 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
static int rule_other = -1; static int rule_other = -1;
assert(u->number); assert(u->number);
assert(btype->construction);
if (eff_skill(u, SK_BUILDING, r) == 0) { if (eff_skill(u, SK_BUILDING, r) == 0) {
cmistake(u, ord, 101, MSG_PRODUCE); cmistake(u, ord, 101, MSG_PRODUCE);
return; return 0;
} }
/* Falls eine Nummer angegeben worden ist, und ein Gebaeude mit der /* Falls eine Nummer angegeben worden ist, und ein Gebaeude mit der
@ -670,7 +671,6 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
* baut man an der eigenen burg weiter. */ * baut man an der eigenen burg weiter. */
/* Wenn die angegebene Nummer falsch ist, KEINE Burg bauen! */ /* Wenn die angegebene Nummer falsch ist, KEINE Burg bauen! */
id = getid();
if (id > 0) { /* eine Nummer angegeben, keine neue Burg bauen */ if (id > 0) { /* eine Nummer angegeben, keine neue Burg bauen */
b = findbuilding(id); b = findbuilding(id);
if (!b || b->region != u->region) { /* eine Burg mit dieser Nummer gibt es hier nicht */ if (!b || b->region != u->region) { /* eine Burg mit dieser Nummer gibt es hier nicht */
@ -680,7 +680,7 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
} else { } else {
/* keine neue Burg anfangen wenn eine Nummer angegeben war */ /* keine neue Burg anfangen wenn eine Nummer angegeben war */
cmistake(u, ord, 6, MSG_PRODUCE); cmistake(u, ord, 6, MSG_PRODUCE);
return; return 0;
} }
} }
} else if (u->building && u->building->type == btype) { } else if (u->building && u->building->type == btype) {
@ -693,27 +693,27 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
if (fval(btype, BTF_UNIQUE) && buildingtype_exists(r, btype, false)) { if (fval(btype, BTF_UNIQUE) && buildingtype_exists(r, btype, false)) {
/* only one of these per region */ /* only one of these per region */
cmistake(u, ord, 93, MSG_PRODUCE); cmistake(u, ord, 93, MSG_PRODUCE);
return; return 0;
} }
if (besieged(u)) { if (besieged(u)) {
/* units under siege can not build */ /* units under siege can not build */
cmistake(u, ord, 60, MSG_PRODUCE); cmistake(u, ord, 60, MSG_PRODUCE);
return; return 0;
} }
if (btype->flags & BTF_NOBUILD) { if (btype->flags & BTF_NOBUILD) {
/* special building, cannot be built */ /* special building, cannot be built */
cmistake(u, ord, 221, MSG_PRODUCE); cmistake(u, ord, 221, MSG_PRODUCE);
return; return 0;
} }
if (r->terrain->max_road <= 0) { if ((r->terrain->flags & LAND_REGION) == 0) {
/* special terrain, cannot build */ /* special terrain, cannot build */
cmistake(u, ord, 221, MSG_PRODUCE); cmistake(u, ord, 221, MSG_PRODUCE);
return; return 0;
} }
if (btype->flags & BTF_ONEPERTURN) { if (btype->flags & BTF_ONEPERTURN) {
if (b && fval(b, BLD_EXPANDED)) { if (b && fval(b, BLD_EXPANDED)) {
cmistake(u, ord, 318, MSG_PRODUCE); cmistake(u, ord, 318, MSG_PRODUCE);
return; return 0;
} }
n = 1; n = 1;
} }
@ -726,7 +726,7 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
unit *owner = building_owner(b); unit *owner = building_owner(b);
if (!owner || owner->faction != u->faction) { if (!owner || owner->faction != u->faction) {
cmistake(u, ord, 1222, MSG_PRODUCE); cmistake(u, ord, 1222, MSG_PRODUCE);
return; return 0;
} }
} }
} }
@ -754,18 +754,20 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
case ECOMPLETE: case ECOMPLETE:
/* the building is already complete */ /* the building is already complete */
cmistake(u, ord, 4, MSG_PRODUCE); cmistake(u, ord, 4, MSG_PRODUCE);
return; break;
case ENOMATERIALS: case ENOMATERIALS:
ADDMSG(&u->faction->msgs, msg_materials_required(u, ord, ADDMSG(&u->faction->msgs, msg_materials_required(u, ord,
btype->construction, want)); btype->construction, want));
return; break;
case ELOWSKILL: case ELOWSKILL:
case ENEEDSKILL: case ENEEDSKILL:
/* no skill, or not enough skill points to build */ /* no skill, or not enough skill points to build */
cmistake(u, ord, 50, MSG_PRODUCE); cmistake(u, ord, 50, MSG_PRODUCE);
return; break;
}
if (built<=0) {
return built;
} }
/* at this point, the building size is increased. */ /* at this point, the building size is increased. */
if (b == NULL) { if (b == NULL) {
/* build a new building */ /* build a new building */
@ -784,7 +786,6 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
a->data.i = u->faction->alliance->id; a->data.i = u->faction->alliance->id;
} }
#endif #endif
} }
btname = LOC(lang, btype->_name); btname = LOC(lang, btype->_name);
@ -824,6 +825,7 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
ADDMSG(&u->faction->msgs, msg_message("buildbuilding", ADDMSG(&u->faction->msgs, msg_message("buildbuilding",
"building unit size", b, u, built)); "building unit size", b, u, built));
return built;
} }
static void build_ship(unit * u, ship * sh, int want) static void build_ship(unit * u, ship * sh, int want)

78
src/kernel/build.test.c Normal file
View File

@ -0,0 +1,78 @@
#include <platform.h>
#include "types.h"
#include "build.h"
#include "order.h"
#include "unit.h"
#include "building.h"
#include "faction.h"
#include "region.h"
#include "race.h"
#include "item.h"
#include <util/language.h>
#include <CuTest.h>
#include <tests.h>
#include <assert.h>
static void test_build_building_no_materials(CuTest *tc) {
unit *u;
region *r;
faction *f;
race *rc;
const building_type *btype;
test_cleanup();
test_create_world();
rc = test_create_race("human");
r = findregion(0, 0);
f = test_create_faction(rc);
assert(rc && f && r);
u = test_create_unit(f, r);
btype = bt_find("castle");
assert(u && btype);
set_level(u, SK_BUILDING, 1);
CuAssertIntEquals(tc, ENOMATERIALS, build_building(u, btype, 0, 4, 0));
CuAssertPtrEquals(tc, 0, r->buildings);
CuAssertPtrEquals(tc, 0, u->building);
}
static void test_build_building_success(CuTest *tc) {
unit *u;
region *r;
faction *f;
race *rc;
const building_type *btype;
const resource_type *rtype;
test_cleanup();
test_create_world();
rc = test_create_race("human");
rtype = get_resourcetype(R_STONE);
btype = bt_find("castle");
assert(btype && rc && rtype && rtype->itype);
// TODO: assert(btype->construction);
r = findregion(0, 0);
assert(!r->buildings);
f = test_create_faction(rc);
assert(r && f);
u = test_create_unit(f, r);
assert(u);
i_change(&u->items, rtype->itype, 1);
set_level(u, SK_BUILDING, 1);
CuAssertIntEquals(tc, 1, build_building(u, btype, 0, 4, 0));
CuAssertPtrNotNull(tc, r->buildings);
CuAssertPtrEquals(tc, r->buildings, u->building);
CuAssertIntEquals(tc, 1, u->building->size);
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
}
CuSuite *get_build_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_build_building_success);
SUITE_ADD_TEST(suite, test_build_building_no_materials);
return suite;
}

View File

@ -125,8 +125,8 @@ extern "C" {
extern int buildingcapacity(const struct building *b); extern int buildingcapacity(const struct building *b);
extern struct building *new_building(const struct building_type *typ, extern struct building *new_building(const struct building_type *typ,
struct region *r, const struct locale *lang); struct region *r, const struct locale *lang);
void build_building(struct unit *u, const struct building_type *typ, int size, int build_building(struct unit *u, const struct building_type *typ,
struct order *ord); int id, int size, struct order *ord);
/* Alte Gebäudetypen: */ /* Alte Gebäudetypen: */

View File

@ -329,6 +329,35 @@ void json_ships(cJSON *json) {
} }
} }
void json_locale(cJSON *json, struct locale *lang) {
cJSON *child;
if (json->type!=cJSON_Object) {
log_error_n("strings is not a json object: %d", json->type);
return;
}
for (child=json->child;child;child=child->next) {
if (child->type==cJSON_String) {
locale_setstring(lang, child->string, child->valuestring);
}
}
}
void json_strings(cJSON *json) {
cJSON *child;
if (json->type!=cJSON_Object) {
log_error_n("strings is not a json object: %d", json->type);
return;
}
for (child=json->child;child;child=child->next) {
if ((child->type==cJSON_Object)) {
struct locale *lang = get_or_create_locale(child->string);
json_locale(child, lang);
} else {
log_error_n("strings for locale `%s` are not a json object: %d", child->string, child->type);
}
}
}
static void json_direction(cJSON *json, struct locale *lang) { static void json_direction(cJSON *json, struct locale *lang) {
cJSON *child; cJSON *child;
if (json->type!=cJSON_Object) { if (json->type!=cJSON_Object) {
@ -476,6 +505,9 @@ void json_config(cJSON *json) {
else if (strcmp(child->string, "ships")==0) { else if (strcmp(child->string, "ships")==0) {
json_ships(child); json_ships(child);
} }
else if (strcmp(child->string, "strings")==0) {
json_strings(child);
}
else if (strcmp(child->string, "directions")==0) { else if (strcmp(child->string, "directions")==0) {
json_directions(child); json_directions(child);
} }

View File

@ -262,6 +262,23 @@ static void test_keywords(CuTest * tc)
test_cleanup(); test_cleanup();
} }
static void test_strings(CuTest * tc)
{
const char * data = "{\"strings\": { \"de\" : { \"move\" : \"NACH\", \"study\" : \"LERNEN\" }}}";
const struct locale * lang;
cJSON *json = cJSON_Parse(data);
CuAssertPtrNotNull(tc, json);
test_cleanup();
lang = get_or_create_locale("de");
CuAssertPtrNotNull(tc, lang);
CuAssertPtrEquals(tc, NULL, (void *)locale_string(lang, "move"));
json_config(json);
CuAssertStrEquals(tc, "NACH", locale_string(lang, "move"));
CuAssertStrEquals(tc, "LERNEN", locale_string(lang, "study"));
}
CuSuite *get_jsonconf_suite(void) CuSuite *get_jsonconf_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
@ -273,6 +290,7 @@ CuSuite *get_jsonconf_suite(void)
SUITE_ADD_TEST(suite, test_buildings); SUITE_ADD_TEST(suite, test_buildings);
SUITE_ADD_TEST(suite, test_terrains); SUITE_ADD_TEST(suite, test_terrains);
SUITE_ADD_TEST(suite, test_races); SUITE_ADD_TEST(suite, test_races);
SUITE_ADD_TEST(suite, test_strings);
SUITE_ADD_TEST(suite, test_flags); SUITE_ADD_TEST(suite, test_flags);
return suite; return suite;
} }

View File

@ -16,6 +16,7 @@ CuSuite *get_item_suite(void);
CuSuite *get_magic_suite(void); CuSuite *get_magic_suite(void);
CuSuite *get_move_suite(void); CuSuite *get_move_suite(void);
CuSuite *get_pool_suite(void); CuSuite *get_pool_suite(void);
CuSuite *get_build_suite(void);
CuSuite *get_reports_suite(void); CuSuite *get_reports_suite(void);
CuSuite *get_ship_suite(void); CuSuite *get_ship_suite(void);
CuSuite *get_spellbook_suite(void); CuSuite *get_spellbook_suite(void);
@ -52,6 +53,7 @@ int RunAllTests(void)
CuSuiteAddSuite(suite, get_functions_suite()); CuSuiteAddSuite(suite, get_functions_suite());
CuSuiteAddSuite(suite, get_umlaut_suite()); CuSuiteAddSuite(suite, get_umlaut_suite());
/* kernel */ /* kernel */
CuSuiteAddSuite(suite, get_build_suite());
CuSuiteAddSuite(suite, get_pool_suite()); CuSuiteAddSuite(suite, get_pool_suite());
CuSuiteAddSuite(suite, get_curse_suite()); CuSuiteAddSuite(suite, get_curse_suite());
CuSuiteAddSuite(suite, get_equipment_suite()); CuSuiteAddSuite(suite, get_equipment_suite());

View File

@ -102,12 +102,20 @@ ship_type * test_create_shiptype(const char ** names)
building_type * test_create_buildingtype(const char * name) building_type * test_create_buildingtype(const char * name)
{ {
building_type * btype = (building_type*)calloc(sizeof(building_type), 1); building_type *btype = (building_type *)calloc(sizeof(building_type), 1);
btype->flags = BTF_NAMECHANGE; btype->flags = BTF_NAMECHANGE;
btype->_name = _strdup(name); btype->_name = _strdup(name);
locale_setstring(default_locale, name, name); btype->construction = (construction *)calloc(sizeof(construction), 1);
bt_register(btype); btype->construction->skill = SK_BUILDING;
return btype; btype->construction->maxsize = -1;
btype->construction->minskill = 1;
btype->construction->reqsize = 1;
btype->construction->materials = (requirement *)calloc(sizeof(requirement), 1);
btype->construction->materials->number = 1;
btype->construction->materials->rtype = get_resourcetype(R_STONE);
locale_setstring(default_locale, name, name);
bt_register(btype);
return btype;
} }
item_type * test_create_itemtype(const char ** names) { item_type * test_create_itemtype(const char ** names) {
@ -143,6 +151,7 @@ void test_create_world(void)
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION); t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION);
t_plain->size = 1000; t_plain->size = 1000;
t_plain->max_road = 100;
t_ocean = test_create_terrain("ocean", SEA_REGION | SAIL_INTO | SWIM_INTO); t_ocean = test_create_terrain("ocean", SEA_REGION | SAIL_INTO | SWIM_INTO);
t_ocean->size = 0; t_ocean->size = 0;