fixed two bugs: harbours were not unique and multiple instances of unique buildings could still be built

This commit is contained in:
Enno Rehling 2011-03-09 00:25:51 +01:00
parent d65d03db9c
commit 8714957a61
9 changed files with 287 additions and 21 deletions

View File

@ -128,7 +128,7 @@
</construction> </construction>
</building> </building>
<building name="harbour" capacity="1" maxcapacity="25" maxsize="25"> <building name="harbour" capacity="1" maxcapacity="25" maxsize="25" unique="yes">
<maintenance type="money" amount="250" vital="yes"/> <maintenance type="money" amount="250" vital="yes"/>
<construction skill="building" minskill="3" reqsize="25" maxsize="25"> <construction skill="building" minskill="3" reqsize="25" maxsize="25">
<requirement type="log" quantity="125"/> <requirement type="log" quantity="125"/>

View File

@ -5,6 +5,19 @@ local function _test_create_ship(r)
return s return s
end end
local function _test_unique_btype()
local utype = nil
for i = 1, #config.buildings do
bt = config.buildings[i]
if (((config.get_building(bt).flags / 4) % 2) ~= 0) then -- #define BTF_UNIQUE 0x04
if (((config.get_building(bt).flags / 2) % 2) == 0) then -- #define BTF_NOBUILD 0x02
utype = bt
end
end
end
return utype
end
local function one_unit(r, f) local function one_unit(r, f)
local u = unit.create(f, r, 1) local u = unit.create(f, r, 1)
u:add_item("money", u.number * 100) u:add_item("money", u.number * 100)
@ -943,3 +956,97 @@ function test_bson_with_multiple_attribs()
end end
assert_equal(6, total) assert_equal(6, total)
end end
function test_building_unique0()
local r = region.create(0, 0, "mountain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 20)
local f2 = faction.create("noreply@eressea.de", "human", "de")
local u2 = unit.create(f2, r, 20)
local utype = _test_unique_btype()
if (utype ~= nil) then
assert_equal("harbour", utype)
u:set_skill("building", 20)
u:add_item("log", 10000)
u:add_item("iron", 10000)
u:add_item("stone", 10000)
u:add_item("money", 10000)
u2:set_skill("building", 20)
u2:add_item("log", 10000)
u2:add_item("iron", 10000)
u2:add_item("stone", 10000)
u2:add_item("money", 10000)
-- build two harbours in one go
u:clear_orders()
u:add_order("MACHEN ".. translate(utype))
u2:clear_orders()
u2:add_order("MACHEN ".. translate(utype))
process_orders()
assert_not_nil(r.buildings)
bcount = 0
for bs in r.buildings do
assert_equal(1, string.find(bs.name, translate(utype)))
if (bs.size >= config.get_building(utype).maxsize) then
bcount = bcount + 1
end
end
assert_equal(1, bcount) -- only one should be completed
else
-- fail() -- no unique building in rules
end
end
function test_building_unique()
local r = region.create(0, 0, "mountain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 20)
local f2 = faction.create("noreply@eressea.de", "human", "de")
local u2 = unit.create(f2, r, 20)
local utype = _test_unique_btype()
if (utype ~= nil) then
u:set_skill("building", 20)
u:add_item("log", 10000)
u:add_item("iron", 10000)
u:add_item("stone", 10000)
u:add_item("money", 10000)
u2:set_skill("building", 20)
u2:add_item("log", 10000)
u2:add_item("iron", 10000)
u2:add_item("stone", 10000)
u2:add_item("money", 10000)
-- start building two harbours
u:clear_orders()
u:add_order("MACHEN 1 Hafen")
u2:clear_orders()
u2:add_order("MACHEN 1 Hafen")
process_orders()
-- finish building partial harbours
u:clear_orders()
u:add_order("MACHEN ".. translate("harbour"))
u2:clear_orders()
u2:add_order("MACHEN Hafen")
process_orders()
if (r.buildings() == nil) then
process_orders()
end
assert_not_nil(r.buildings)
bcount = 0
local h1 = nil
for bs in r.buildings do
if (h1 == nil) then
h1 = bs.name
else
assert_equal(h1, bs.name)
end
assert_equal(1, string.find(bs.name, "Hafen"))
if (bs.size >= 25) then
bcount = bcount + 1
end
end
assert_equal(1, bcount) -- only one should be completed
end
end

View File

@ -20,6 +20,7 @@ without prior permission by the authors of Eressea.
#include <kernel/config.h> #include <kernel/config.h>
#include <kernel/alliance.h> #include <kernel/alliance.h>
#include <kernel/building.h>
#include <kernel/skill.h> #include <kernel/skill.h>
#include <kernel/equipment.h> #include <kernel/equipment.h>
#include <kernel/calendar.h> #include <kernel/calendar.h>
@ -768,6 +769,19 @@ static int config_get_ships(lua_State * L)
return 1; return 1;
} }
static int config_get_buildings(lua_State * L)
{
quicklist *ql;
int qi, i = 0;
lua_createtable(L, ql_length(buildingtypes), 0);
for (qi = 0, ql = buildingtypes; ql; ql_advance(&ql, &qi, 1)) {
building_type *btype = (building_type *) ql_get(ql, qi);
tolua_pushstring(L, TOLUA_CAST btype->_name);
lua_rawseti(L, -2, ++i);
}
return 1;
}
static int config_get_locales(lua_State * L) static int config_get_locales(lua_State * L)
{ {
const struct locale *lang; const struct locale *lang;
@ -823,6 +837,136 @@ static int config_get_resource(lua_State * L)
return 0; return 0;
} }
static int config_get_btype(lua_State * L)
{
const char *name = tolua_tostring(L, 1, 0);
if (name) {
const struct building_type *btype = bt_find(name);
if (btype) {
lua_newtable(L);
lua_pushstring(L, "flags");
lua_pushinteger(L, btype->flags);
lua_settable(L, -3);
if (btype->capacity > 0) {
lua_pushstring(L, "capacity");
lua_pushinteger(L, btype->capacity);
lua_settable(L, -3);
}
if (btype->maxcapacity > 0) {
lua_pushstring(L, "maxcapacity");
lua_pushinteger(L, btype->maxcapacity);
lua_settable(L, -3);
}
if (btype->maxsize > 0) {
lua_pushstring(L, "maxsize");
lua_pushinteger(L, btype->maxsize);
lua_settable(L, -3);
}
if (btype->maintenance) {
int i;
lua_pushstring(L, "maintenance");
lua_newtable(L);
for (i = 0; btype->maintenance[i].number; ++i) {
lua_pushstring(L,
btype->maintenance[i].rtype->_name[0]);
lua_pushinteger(L, btype->maintenance[i].number);
lua_settable(L, -3);
}
lua_settable(L, -3);
}
if (btype->construction) {
int i;
lua_pushstring(L, "build_skill_min");
lua_pushinteger(L, btype->construction->minskill);
lua_settable(L, -3);
lua_pushstring(L, "build_skill_name");
lua_pushstring(L, skillnames[btype->construction->skill]);
lua_settable(L, -3);
if (btype->construction->materials) {
lua_pushstring(L, "materials");
lua_newtable(L);
for (i = 0; btype->construction->materials[i].number; ++i) {
lua_pushstring(L,
btype->construction->materials[i].rtype->_name[0]);
lua_pushinteger(L, btype->construction->materials[i].number);
lua_settable(L, -3);
}
lua_settable(L, -3);
}
}
return 1;
}
}
return 0;
}
static int config_get_stype(lua_State * L)
{
const char *name = tolua_tostring(L, 1, 0);
if (name) {
const struct ship_type *stype = st_find(name);
if (stype) {
lua_newtable(L);
lua_pushstring(L, "range");
lua_pushinteger(L, stype->range);
lua_settable(L, -3);
lua_pushstring(L, "cabins");
lua_pushinteger(L, stype->cabins);
lua_settable(L, -3);
lua_pushstring(L, "cargo");
lua_pushinteger(L, stype->cargo);
lua_settable(L, -3);
lua_pushstring(L, "cptskill");
lua_pushinteger(L, stype->cptskill);
lua_settable(L, -3);
lua_pushstring(L, "minskill");
lua_pushinteger(L, stype->minskill);
lua_settable(L, -3);
lua_pushstring(L, "sumskill");
lua_pushinteger(L, stype->sumskill);
lua_settable(L, -3);
lua_pushstring(L, "fishing");
lua_pushinteger(L, stype->fishing);
lua_settable(L, -3);
if (stype->coasts) {
const terrain_type *coast = *stype->coasts;
lua_pushstring(L, "coasts");
lua_newtable(L);
while(coast) {
lua_pushstring(L, coast->_name);
lua_pushinteger(L, 1);
lua_settable(L, -3);
coast = coast->next;
}
}
if (stype->construction) {
int i;
lua_pushstring(L, "build_skill_min");
lua_pushinteger(L, stype->construction->minskill);
lua_settable(L, -3);
lua_pushstring(L, "build_skill_name");
lua_pushstring(L, skillnames[stype->construction->skill]);
lua_settable(L, -3);
if (stype->construction->materials) {
lua_pushstring(L, "materials");
lua_newtable(L);
for (i = 0; stype->construction->materials[i].number; ++i) {
lua_pushstring(L,
stype->construction->materials[i].rtype->_name[0]);
lua_pushinteger(L, stype->construction->materials[i].number);
lua_settable(L, -3);
}
lua_settable(L, -3);
}
}
return 1;
}
}
return 0;
}
static int tolua_get_spell_text(lua_State * L) static int tolua_get_spell_text(lua_State * L)
{ {
const struct locale *loc = default_locale; const struct locale *loc = default_locale;
@ -1060,7 +1204,10 @@ int tolua_eressea_open(lua_State * L)
parse_inifile(L, global.inifile, "config"); parse_inifile(L, global.inifile, "config");
tolua_variable(L, TOLUA_CAST "locales", &config_get_locales, 0); tolua_variable(L, TOLUA_CAST "locales", &config_get_locales, 0);
tolua_function(L, TOLUA_CAST "get_resource", &config_get_resource); tolua_function(L, TOLUA_CAST "get_resource", &config_get_resource);
tolua_variable(L, TOLUA_CAST "buildings", &config_get_buildings, 0);
tolua_function(L, TOLUA_CAST "get_building", &config_get_btype);
tolua_variable(L, TOLUA_CAST "ships", &config_get_ships, 0); tolua_variable(L, TOLUA_CAST "ships", &config_get_ships, 0);
tolua_function(L, TOLUA_CAST "get_ship", &config_get_stype);
} tolua_endmodule(L); } tolua_endmodule(L);
tolua_function(L, TOLUA_CAST "get_region_by_id", tolua_get_region_byid); tolua_function(L, TOLUA_CAST "get_region_by_id", tolua_get_region_byid);
tolua_function(L, TOLUA_CAST "get_faction", tolua_get_faction); tolua_function(L, TOLUA_CAST "get_faction", tolua_get_faction);

View File

@ -890,7 +890,7 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
if (b) if (b)
btype = b->type; btype = b->type;
if (b && 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;

View File

@ -124,28 +124,28 @@ typedef struct building_typelist {
building_type *type; building_type *type;
} building_typelist; } building_typelist;
static building_typelist *buildingtypes; quicklist *buildingtypes = NULL;
building_type *bt_find(const char *name) building_type *bt_find(const char *name)
{ {
const struct building_typelist *btl = buildingtypes; quicklist *ql;
int qi;
assert(name); assert(name);
while (btl && strcmp(btl->type->_name, name))
btl = btl->next; for (qi = 0, ql = buildingtypes; ql; ql_advance(&ql, &qi, 1)) {
if (btl == NULL) { building_type *btype = (building_type *) ql_get(ql, qi);
return NULL; if (strcmp(btype->_name, name) == 0)
return btype;
} }
return btl->type; return NULL;
} }
void bt_register(building_type * type) void bt_register(building_type * type)
{ {
struct building_typelist *btl = malloc(sizeof(building_type));
if (type->init) if (type->init)
type->init(type); type->init(type);
btl->type = type; ql_push(&buildingtypes, (void *)type);
btl->next = buildingtypes;
buildingtypes = btl;
} }
int buildingcapacity(const building * b) int buildingcapacity(const building * b)
@ -362,15 +362,19 @@ const building_type *findbuildingtype(const char *name,
bn = bn->next; bn = bn->next;
} }
if (!bn) { if (!bn) {
struct building_typelist *btl = buildingtypes; quicklist *ql = buildingtypes;
int qi;
bn = calloc(sizeof(local_names), 1); bn = calloc(sizeof(local_names), 1);
bn->next = bnames; bn->next = bnames;
bn->lang = lang; bn->lang = lang;
while (btl) {
const char *n = locale_string(lang, btl->type->_name); for (qi = 0, ql = buildingtypes; ql; ql_advance(&ql, &qi, 1)) {
type.v = (void *)btl->type; building_type *btype = (building_type *) ql_get(ql, qi);
const char *n = locale_string(lang, btype->_name);
type.v = (void *)btype;
addtoken(&bn->names, n, type); addtoken(&bn->names, n, type);
btl = btl->next;
} }
bnames = bn; bnames = bn;
} }

View File

@ -71,6 +71,8 @@ extern "C" {
struct attrib *attribs; struct attrib *attribs;
} building_type; } building_type;
extern struct quicklist *buildingtypes;
extern building_type *bt_find(const char *name); extern building_type *bt_find(const char *name);
extern void register_buildings(void); extern void register_buildings(void);
extern void bt_register(struct building_type *type); extern void bt_register(struct building_type *type);

View File

@ -2715,3 +2715,7 @@ void follow_unit(unit * u)
} }
} }
} }
#ifndef DISABLE_TESTS
#include "move_test.c"
#endif

View File

@ -69,10 +69,10 @@ const ship_type *findshiptype(const char *name, const struct locale *lang)
for (qi = 0, ql = shiptypes; ql; ql_advance(&ql, &qi, 1)) { for (qi = 0, ql = shiptypes; ql; ql_advance(&ql, &qi, 1)) {
ship_type *stype = (ship_type *) ql_get(ql, qi); ship_type *stype = (ship_type *) ql_get(ql, qi);
variant var; variant var2;
const char *n = locale_string(lang, stype->name[0]); const char *n = locale_string(lang, stype->name[0]);
var.v = (void *)stype; var2.v = (void *)stype;
addtoken(&sn->names, n, var); addtoken(&sn->names, n, var2);
} }
snames = sn; snames = sn;
} }

View File

@ -9,6 +9,7 @@
CuSuite *get_curse_suite(void); CuSuite *get_curse_suite(void);
CuSuite *get_market_suite(void); CuSuite *get_market_suite(void);
CuSuite *get_move_suite(void);
CuSuite *get_laws_suite(void); CuSuite *get_laws_suite(void);
#include <kernel/region.h> #include <kernel/region.h>
@ -34,6 +35,7 @@ int RunAllTests(void)
CuSuiteAddSuite(suite, get_quicklist_suite()); CuSuiteAddSuite(suite, get_quicklist_suite());
CuSuiteAddSuite(suite, get_curse_suite()); CuSuiteAddSuite(suite, get_curse_suite());
CuSuiteAddSuite(suite, get_market_suite()); CuSuiteAddSuite(suite, get_market_suite());
CuSuiteAddSuite(suite, get_move_suite());
CuSuiteAddSuite(suite, get_laws_suite()); CuSuiteAddSuite(suite, get_laws_suite());
CuSuiteRun(suite); CuSuiteRun(suite);