Bug 2606: DRY, share code between buy and sell.

This commit is contained in:
Enno Rehling 2019-09-08 13:29:10 +02:00
parent d2d782c761
commit 007721991d
4 changed files with 64 additions and 45 deletions

View file

@ -1189,6 +1189,18 @@ bool trade_needs_castle(const terrain_type *terrain, const race *rc)
return rc != rc_insect && (terrain == t_swamp || terrain == t_desert);
}
static building * first_building(region *r, const struct building_type *btype, int minsize) {
building *b = NULL;
if (r->buildings) {
for (b = r->buildings; b; b = b->next) {
if (b->type == btype && b->size >= minsize) {
return b;
}
}
}
return NULL;
}
static void buy(unit * u, econ_request ** buyorders, struct order *ord)
{
char token[128];
@ -1223,21 +1235,12 @@ static void buy(unit * u, econ_request ** buyorders, struct order *ord)
/* Entweder man ist Insekt in Sumpf/Wueste, oder es muss
* einen Handelsposten in der Region geben: */
if (trade_needs_castle(r->terrain, u_race(u))) {
building *b = NULL;
if (r->buildings) {
static int cache;
static const struct building_type *bt_castle;
if (bt_changed(&cache)) {
bt_castle = bt_find("castle");
}
for (b = r->buildings; b; b = b->next) {
if (b->type == bt_castle && b->size >= 2) {
break;
}
}
static int cache;
static const struct building_type *castle_bt;
if (bt_changed(&cache)) {
castle_bt = bt_find("castle");
}
if (b == NULL) {
if (first_building(r, castle_bt, 2) == NULL) {
cmistake(u, ord, 119, MSG_COMMERCE);
return;
}
@ -1540,29 +1543,14 @@ static bool sell(unit * u, econ_request ** sellorders, struct order *ord)
return false;
}
}
/* In der Region muss es eine Burg geben. */
if (u_race(u) == get_race(RC_INSECT)) {
if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT)
&& !rbuildings(r)) {
if (trade_needs_castle(r->terrain, u_race(u))) {
/* In der Region muss es eine Burg geben. */
if (first_building(r, castle_bt, 2) == NULL) {
cmistake(u, ord, 119, MSG_COMMERCE);
return false;
}
}
else {
/* ...oder in der Region muss es eine Burg geben. */
building *b = 0;
if (r->buildings) {
for (b = r->buildings; b; b = b->next) {
if (b->type == castle_bt && b->size >= 2) break;
}
}
if (!b) {
cmistake(u, ord, 119, MSG_COMMERCE);
return false;
}
}
/* Ein Haendler kann nur 10 Gueter pro Talentpunkt verkaufen. */
i = u->number * 10 * effskill(u, SK_TRADE, NULL);

View file

@ -237,7 +237,10 @@ static void test_trade_needs_castle(CuTest *tc) {
/* Handeln ist nur in Regionen mit Burgen möglich. */
race *rc;
region *r;
unit *u;
building *b;
const terrain_type *t_swamp;
const item_type *it_luxury;
test_setup();
setup_production();
@ -246,9 +249,32 @@ static void test_trade_needs_castle(CuTest *tc) {
init_terrains();
t_swamp = get_terrain("swamp");
r = setup_trade_region(tc, t_swamp);
rc = test_create_race(NULL);
it_luxury = r_luxury(r);
rc = test_create_race(NULL);
CuAssertTrue(tc, trade_needs_castle(t_swamp, rc));
u = test_create_unit(test_create_faction(rc), r);
unit_addorder(u, create_order(K_BUY, u->faction->locale, "1 %s",
LOC(u->faction->locale, resourcename(it_luxury->rtype, 0))));
unit_addorder(u, create_order(K_SELL, u->faction->locale, "1 %s",
LOC(u->faction->locale, resourcename(it_luxury->rtype, 0))));
produce(r);
CuAssertIntEquals(tc, 2, test_count_messagetype(u->faction->msgs, "error119"));
test_clear_messages(u->faction);
freset(u, UFL_LONGACTION);
b = test_create_building(r, test_create_buildingtype("castle"));
b->size = 1;
produce(r);
CuAssertIntEquals(tc, 2, test_count_messagetype(u->faction->msgs, "error119"));
test_clear_messages(u->faction);
freset(u, UFL_LONGACTION);
b->size = 2;
test_clear_messages(u->faction);
produce(r);
CuAssertIntEquals(tc, 0, test_count_messagetype(u->faction->msgs, "error119"));
test_teardown();
}
@ -259,7 +285,6 @@ static void test_trade_insect(CuTest *tc) {
race *rc;
const terrain_type *t_swamp;
const item_type *it_luxury;
const item_type *it_silver;
test_setup();
setup_production();
@ -273,21 +298,13 @@ static void test_trade_insect(CuTest *tc) {
it_luxury = r_luxury(r);
CuAssertTrue(tc, !trade_needs_castle(t_swamp, rc));
CuAssertPtrNotNull(tc, it_luxury);
it_silver = get_resourcetype(R_SILVER)->itype;
u = setup_trade_unit(tc, r, rc);
unit_addorder(u, create_order(K_BUY, u->faction->locale, "1 %s",
LOC(u->faction->locale, resourcename(it_luxury->rtype, 0))));
test_set_item(u, it_silver, 10);
CuAssertPtrEquals(tc, r, u->region);
CuAssertPtrEquals(tc, (void *)it_luxury, (void *)r_luxury(u->region));
unit_addorder(u, create_order(K_SELL, u->faction->locale, "1 %s",
LOC(u->faction->locale, resourcename(it_luxury->rtype, 0))));
produce(u->region);
CuAssertPtrEquals(tc, NULL, test_find_messagetype(u->faction->msgs, "error119"));
CuAssertIntEquals(tc, 1, get_item(u, it_luxury));
CuAssertIntEquals(tc, 5, get_item(u, it_silver));
terraform_region(r, get_terrain("swamp"));
CuAssertIntEquals(tc, 0, test_count_messagetype(u->faction->msgs, "error119"));
test_teardown();
}

View file

@ -591,6 +591,19 @@ struct message * test_find_messagetype(struct message_list *msgs, const char *na
return test_find_messagetype_ex(msgs, name, NULL);
}
int test_count_messagetype(struct message_list *msgs, const char *name)
{
int count = 0;
struct mlist *ml;
if (!msgs) return 0;
for (ml = msgs->begin; ml; ml = ml->next) {
if (strcmp(name, test_get_messagetype(ml->msg)) == 0) {
++count;
}
}
return count;
}
void test_clear_messagelist(message_list **msgs) {
if (*msgs) {
free_messagelist((*msgs)->begin);

View file

@ -64,6 +64,7 @@ extern "C" {
void test_translate_param(const struct locale *lang, enum param_t param, const char *text);
const char * test_get_messagetype(const struct message *msg);
int test_count_messagetype(struct message_list *msgs, const char *name);
struct message * test_find_messagetype_ex(struct message_list *msgs, const char *name, struct message *prev);
struct message * test_find_messagetype(struct message_list *msgs, const char *name);
struct message * test_get_last_message(struct message_list *mlist);