XML construction elements never have a building.

required buildings are encoded by RMT_PROD_REQUIRE.
improved error messaging.
This commit is contained in:
Enno Rehling 2017-05-06 15:53:21 +02:00
parent b74d18b8c9
commit 898c12e99a
11 changed files with 22 additions and 73 deletions

View File

@ -27,7 +27,7 @@ function test_laen_needs_mine()
turn_process() turn_process()
assert_equal(0, u:get_item('laen')) assert_equal(0, u:get_item('laen'))
assert_equal(100, r:get_resource('laen')) assert_equal(100, r:get_resource('laen'))
assert_equal(1, f:count_msg_type("error104")) -- requires building assert_equal(1, f:count_msg_type("building_needed")) -- requires building
u.building = building.create(u.region, "mine") u.building = building.create(u.region, "mine")
u.building.working = true u.building.working = true

View File

@ -814,6 +814,7 @@ static struct message * get_modifiers(unit *u, skill_t sk, const resource_type *
int skill = 0; int skill = 0;
int need_race = 0, need_bldg = 0; int need_race = 0, need_bldg = 0;
resource_mod *mod; resource_mod *mod;
const struct building_type *btype_needed = NULL;
if (btype && btype->modifiers) { if (btype && btype->modifiers) {
for (mod = btype->modifiers; mod && mod->type != RMT_END; ++mod) { for (mod = btype->modifiers; mod && mod->type != RMT_END; ++mod) {
@ -838,7 +839,9 @@ static struct message * get_modifiers(unit *u, skill_t sk, const resource_type *
break; break;
case RMT_PROD_REQUIRE: case RMT_PROD_REQUIRE:
if (mod->race) need_race |= 1; if (mod->race) need_race |= 1;
if (mod->btype) need_bldg |= 1; if (mod->btype) {
need_bldg |= 1;
}
break; break;
default: default:
/* is not a production modifier, ignore it */ /* is not a production modifier, ignore it */
@ -848,14 +851,17 @@ static struct message * get_modifiers(unit *u, skill_t sk, const resource_type *
} }
if (mod->type == RMT_PROD_REQUIRE) { if (mod->type == RMT_PROD_REQUIRE) {
if (mod->race) need_race |= 2; if (mod->race) need_race |= 2;
if (mod->btype) need_bldg |= 2; if (mod->btype) {
btype_needed = mod->btype;
need_bldg |= 2;
}
} }
} }
if (need_race == 2) { if (need_race == 2) {
return msg_error(u, u->thisorder, 117); return msg_error(u, u->thisorder, 117);
} }
if (need_bldg == 2) { if (btype_needed && need_bldg == 2) {
return msg_error(u, u->thisorder, 104); return msg_feedback(u, u->thisorder, "building_needed", "building", btype_needed->_name);
} }
*skillp = skill; *skillp = skill;
if (savep) *savep = frac_make(save_n, save_d); if (savep) *savep = frac_make(save_n, save_d);
@ -885,11 +891,6 @@ static void manufacture(unit * u, const item_type * itype, int want)
ADDMSG(&u->faction->msgs, ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); msg_feedback(u, u->thisorder, "skill_needed", "skill", sk));
return; return;
case EBUILDINGREQ:
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "building_needed", "building",
itype->construction->extra.btype->_name));
return;
case ELOWSKILL: case ELOWSKILL:
ADDMSG(&u->faction->msgs, ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "manufacture_skills", msg_feedback(u, u->thisorder, "manufacture_skills",
@ -1236,11 +1237,6 @@ static void create_potion(unit * u, const potion_type * ptype, int want)
/* no skill, or not enough skill points to build */ /* no skill, or not enough skill points to build */
cmistake(u, u->thisorder, 50, MSG_PRODUCE); cmistake(u, u->thisorder, 50, MSG_PRODUCE);
break; break;
case EBUILDINGREQ:
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "building_needed", "building",
ptype->itype->construction->extra.btype->_name));
break;
case ECOMPLETE: case ECOMPLETE:
assert(0); assert(0);
break; break;

View File

@ -527,7 +527,7 @@ static void test_modify_production(CuTest *tc) {
test_clear_messages(u->faction); test_clear_messages(u->faction);
make_item(u, itype, 10); make_item(u, itype, 10);
CuAssertIntEquals(tc, 28, get_item(u, itype)); CuAssertIntEquals(tc, 28, get_item(u, itype));
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error104")); CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "building_needed"));
rtype->modifiers[0].type = RMT_PROD_REQUIRE; rtype->modifiers[0].type = RMT_PROD_REQUIRE;
rtype->modifiers[0].race = test_create_race("smurf"); rtype->modifiers[0].race = test_create_race("smurf");

View File

@ -513,17 +513,6 @@ int build(unit * u, const construction * ctype, int completed, int want, int ski
return ENOMATERIALS; return ENOMATERIALS;
if (con->improvement == NULL && completed == con->maxsize) if (con->improvement == NULL && completed == con->maxsize)
return ECOMPLETE; return ECOMPLETE;
if (con->type==CONS_ITEM && con->extra.btype) {
building *b;
if (!u->building || u->building->type != con->extra.btype) {
return EBUILDINGREQ;
}
b = inside_building(u);
if (!b || !building_is_active(b)) {
return EBUILDINGREQ;
}
}
if (con->skill != NOSKILL) { if (con->skill != NOSKILL) {
int effsk; int effsk;
int dm = get_effect(u, oldpotiontype[P_DOMORE]); int dm = get_effect(u, oldpotiontype[P_DOMORE]);

View File

@ -52,13 +52,8 @@ extern "C" {
int reqsize; /* size of object using up 1 set of requirement. */ int reqsize; /* size of object using up 1 set of requirement. */
requirement *materials; /* material req'd to build one object */ requirement *materials; /* material req'd to build one object */
union { /* only used by CONS_BUILDING: */
/* CONS_BUILDING: */
char * name; /* building level name */ char * name; /* building level name */
/* CONS_ITEM: */
const struct building_type *btype; /* building required to build item */
} extra;
struct construction *improvement; struct construction *improvement;
/* next level, if upgradable. */ /* next level, if upgradable. */
} construction; } construction;
@ -89,7 +84,6 @@ extern "C" {
#define ENEEDSKILL -2 #define ENEEDSKILL -2
#define ECOMPLETE -3 #define ECOMPLETE -3
#define ENOMATERIALS -4 #define ENOMATERIALS -4
#define EBUILDINGREQ -5
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -71,29 +71,6 @@ static void test_build_requires_materials(CuTest *tc) {
teardown_build(&bf); teardown_build(&bf);
} }
static void test_build_requires_building(CuTest *tc) {
build_fixture bf = { 0 };
unit *u;
const struct resource_type *rtype;
building_type *btype;
u = setup_build(&bf);
rtype = bf.cons.materials[0].rtype;
i_change(&u->items, rtype->itype, 1);
set_level(u, SK_ARMORER, 2);
bf.cons.type = CONS_ITEM;
bf.cons.extra.btype = btype = bt_get_or_create("hodor");
btype->maxcapacity = 1;
btype->capacity = 1;
CuAssertIntEquals_Msg(tc, "must be inside a production building", EBUILDINGREQ, build(u, &bf.cons, 0, 1, 0));
u->building = test_create_building(u->region, btype);
fset(u->building, BLD_MAINTAINED);
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1, 0));
btype->maxcapacity = 0;
CuAssertIntEquals_Msg(tc, "cannot build when production building capacity exceeded", EBUILDINGREQ, build(u, &bf.cons, 0, 1, 0));
teardown_build(&bf);
}
static void test_build_failure_missing_skill(CuTest *tc) { static void test_build_failure_missing_skill(CuTest *tc) {
build_fixture bf = { 0 }; build_fixture bf = { 0 };
unit *u; unit *u;
@ -411,7 +388,6 @@ CuSuite *get_build_suite(void)
SUITE_ADD_TEST(suite, test_build_failure_low_skill); SUITE_ADD_TEST(suite, test_build_failure_low_skill);
SUITE_ADD_TEST(suite, test_build_failure_missing_skill); SUITE_ADD_TEST(suite, test_build_failure_missing_skill);
SUITE_ADD_TEST(suite, test_build_requires_materials); SUITE_ADD_TEST(suite, test_build_requires_materials);
SUITE_ADD_TEST(suite, test_build_requires_building);
SUITE_ADD_TEST(suite, test_build_failure_completed); SUITE_ADD_TEST(suite, test_build_failure_completed);
SUITE_ADD_TEST(suite, test_build_with_ring); SUITE_ADD_TEST(suite, test_build_with_ring);
SUITE_ADD_TEST(suite, test_build_with_potion); SUITE_ADD_TEST(suite, test_build_with_potion);

View File

@ -199,14 +199,14 @@ const char *buildingtype(const building_type * btype, const building * b, int bs
if (btype->name) { if (btype->name) {
return btype->name(btype, b, bsize); return btype->name(btype, b, bsize);
} }
if (btype->construction && btype->construction->extra.name) { if (btype->construction && btype->construction->name) {
if (b) { if (b) {
bsize = adjust_size(b, bsize); bsize = adjust_size(b, bsize);
} }
for (con = btype->construction; con; con = con->improvement) { for (con = btype->construction; con; con = con->improvement) {
bsize -= con->maxsize; bsize -= con->maxsize;
if (!con->improvement || bsize <0) { if (!con->improvement || bsize <0) {
return con->extra.name; return con->name;
} }
} }
} }

View File

@ -563,7 +563,7 @@ static void test_buildingtype(CuTest *tc) {
btype = test_create_buildingtype("hodor"); btype = test_create_buildingtype("hodor");
CuAssertPtrNotNull(tc, btype->construction); CuAssertPtrNotNull(tc, btype->construction);
CuAssertStrEquals(tc, "hodor", buildingtype(btype, NULL, 1)); CuAssertStrEquals(tc, "hodor", buildingtype(btype, NULL, 1));
btype->construction->extra.name = strdup("castle"); btype->construction->name = strdup("castle");
CuAssertStrEquals(tc, "castle", buildingtype(btype, NULL, 1)); CuAssertStrEquals(tc, "castle", buildingtype(btype, NULL, 1));
btype = bt_get_or_create("portal"); btype = bt_get_or_create("portal");
CuAssertPtrEquals(tc, NULL, btype->construction); CuAssertPtrEquals(tc, NULL, btype->construction);

View File

@ -248,8 +248,9 @@ void remove_ship(ship ** slist, ship * sh)
void free_ship(ship * s) void free_ship(ship * s)
{ {
while (s->attribs) while (s->attribs) {
a_remove(&s->attribs, s->attribs); a_remove(&s->attribs, s->attribs);
}
free(s->name); free(s->name);
free(s->display); free(s->display);
free(s); free(s);

View File

@ -247,17 +247,10 @@ construction ** consPtr, construct_t type)
con->minskill = xml_ivalue(node, "minskill", -1); con->minskill = xml_ivalue(node, "minskill", -1);
con->reqsize = xml_ivalue(node, "reqsize", 1); con->reqsize = xml_ivalue(node, "reqsize", 1);
if (type == CONS_ITEM) { if (type == CONS_BUILDING) {
propValue = xmlGetProp(node, BAD_CAST "building");
if (propValue != NULL) {
con->extra.btype = bt_get_or_create((const char *)propValue);
xmlFree(propValue);
}
}
else if (type == CONS_BUILDING) {
propValue = xmlGetProp(node, BAD_CAST "name"); propValue = xmlGetProp(node, BAD_CAST "name");
if (propValue != NULL) { if (propValue != NULL) {
con->extra.name = strdup((const char *)propValue); con->name = strdup((const char *)propValue);
xmlFree(propValue); xmlFree(propValue);
} }
} }

View File

@ -479,7 +479,7 @@ static void test_illusioncastle(CuTest *tc)
CuAssertPtrEquals(tc, btype, (void *)icastle_type(a)); CuAssertPtrEquals(tc, btype, (void *)icastle_type(a));
CuAssertPtrEquals(tc, bt_icastle, (void *)b->type); CuAssertPtrEquals(tc, bt_icastle, (void *)b->type);
CuAssertStrEquals(tc, "castle", buildingtype(btype, b, b->size)); CuAssertStrEquals(tc, "castle", buildingtype(btype, b, b->size));
btype->construction->extra.name = strdup("site"); btype->construction->name = strdup("site");
CuAssertStrEquals(tc, "site", buildingtype(btype, b, b->size)); CuAssertStrEquals(tc, "site", buildingtype(btype, b, b->size));
test_cleanup(); test_cleanup();
} }