Skip to content

Commit

Permalink
refactor building stages
Browse files Browse the repository at this point in the history
turning them from a linked list into a dynamic array.
  • Loading branch information
ennorehling committed Mar 9, 2024
1 parent a463a8a commit b24ee03
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 132 deletions.
8 changes: 5 additions & 3 deletions src/economy.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ int destroy_cmd(unit* u, struct order* ord)
return 138;
}
if (n >= b->size) {
building_stage* stage;
ptrdiff_t s, len = arrlen(b->type->a_stages);
/* destroy completly */
/* all units leave the building */
for (u2 = r->units; u2; u2 = u2->next) {
Expand All @@ -530,7 +530,9 @@ int destroy_cmd(unit* u, struct order* ord)
}
}
ADDMSG(&u->faction->msgs, msg_message("destroy", "building unit", b, u));
for (stage = b->type->stages; stage; stage = stage->next) {

for (s = 0; s != len; ++s) {
building_stage *stage = b->type->a_stages + s;
size = recycle(u, &stage->construction, size);
}
remove_building(&r->buildings, b);
Expand Down Expand Up @@ -1188,7 +1190,7 @@ int make_cmd(unit * u, struct order *ord)
if (pl && fval(pl, PFL_NOBUILD)) {
cmistake(u, ord, 275, MSG_PRODUCE);
}
else if (btype->stages) {
else if (btype->a_stages) {
int id = getid();
build_building(u, btype, id, want, ord);
}
Expand Down
2 changes: 1 addition & 1 deletion src/economy.test.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ static void test_sales_taxes(CuTest *tc) {
r_setdemand(r, ltype, 2);
b = test_create_building(r, test_create_castle());
b->size = 10; // 12% sales tax
CuAssertIntEquals(tc, 2, bt_effsize(b->type, b, b->size));
CuAssertIntEquals(tc, 2, buildingeffsize(b, false));

ub = test_create_unit(test_create_faction(), r);
u_set_building(ub, b);
Expand Down
14 changes: 3 additions & 11 deletions src/exparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -1277,8 +1277,9 @@ static void start_buildings(parseinfo *pi, const XML_Char *el, const XML_Char **
}
else if (xml_strequal(el, "construction")) {
assert(stage == NULL);
stage = (building_stage *)calloc(1, sizeof(building_stage));
stage = arraddnptr(btype->a_stages, 1);
if (!stage) abort();
memset(stage, 0, sizeof(building_stage));
parse_construction(&stage->construction, pi, el, attr);
}
else if (xml_strequal(el, "maintenance")) {
Expand Down Expand Up @@ -1477,8 +1478,6 @@ static void end_ships(parseinfo *pi, const XML_Char *el) {

static void end_buildings(parseinfo *pi, const XML_Char *el) {
/* stores the end of the building's stage list: */
static building_stage **stage_ptr;

building_type *btype = (building_type *)pi->object;
if (xml_strequal(el, "construction")) {
assert(btype);
Expand All @@ -1491,18 +1490,11 @@ static void end_buildings(parseinfo *pi, const XML_Char *el) {
con->materials[nreqs].number = 0;
nreqs = 0;
}
if (stage_ptr == NULL) {
/* at the first build stage, initialize stage_ptr: */
assert(btype->stages == NULL);
stage_ptr = &btype->stages;
}
*stage_ptr = stage;
stage_ptr = &stage->next;
stage = NULL;
}
}
else if (xml_strequal(el, "building")) {
stage_ptr = NULL;
stage = NULL;
if (nupkeep > 0) {
btype->maintenance = malloc((1 + (size_t)nupkeep) * sizeof(maintenance));
if (!btype->maintenance) abort();
Expand Down
15 changes: 7 additions & 8 deletions src/jsonconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@ static void json_stage(cJSON *json, building_stage *stage) {

static void json_stages(cJSON *json, building_type *bt) {
cJSON *child;
building_stage *stage, **sp = &bt->stages;
int size = 0;

if (json->type != cJSON_Array) {
Expand All @@ -370,18 +369,18 @@ static void json_stages(cJSON *json, building_type *bt) {
}

for (child = json->child; child; child = child->next) {
building_stage *stage;
switch (child->type) {
case cJSON_Object:
stage = calloc(1, sizeof(building_stage));
stage = arraddnptr(bt->a_stages, 1);
if (!stage) abort();
memset(stage, 0, sizeof(building_stage));
stage->construction.skill = SK_BUILDING;
json_stage(child, stage);
if (stage->construction.maxsize > 0) {
stage->construction.maxsize -= size;
size += stage->construction.maxsize;
}
*sp = stage;
sp = &stage->next;
break;
default:
log_error("building stage contains non-object type %d", child->type);
Expand All @@ -402,7 +401,7 @@ static void json_building(cJSON *json, building_type *bt) {
switch (child->type) {
case cJSON_Array:
if (strcmp(child->string, "stages") == 0) {
if (!bt->stages) {
if (!bt->a_stages) {
json_stages(child, bt);
}
}
Expand All @@ -416,12 +415,12 @@ static void json_building(cJSON *json, building_type *bt) {
case cJSON_Object:
if (strcmp(child->string, "construction") == 0) {
/* simple, single-stage building */
if (!bt->stages) {
building_stage *stage = calloc(1, sizeof(building_stage));
if (!bt->a_stages) {
building_stage *stage = arraddnptr(bt->a_stages, 1);
if (!stage) abort();
memset(stage, 0, sizeof(building_stage));
stage->construction.skill = SK_BUILDING;
json_construction(child, &stage->construction);
bt->stages = stage;
}
}
if (strcmp(child->string, "maintenance") == 0) {
Expand Down
18 changes: 9 additions & 9 deletions src/jsonconf.test.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,25 +389,25 @@ static void test_castles(CuTest *tc) {
CuAssertPtrEquals(tc, NULL, buildingtypes);
json_config(json);

CuAssertPtrNotNull(tc, buildingtypes);
bt = bt_find("castle");
CuAssertPtrNotNull(tc, bt);
CuAssertPtrNotNull(tc, stage = bt->stages);
CuAssertIntEquals(tc, 3, (int)arrlen(bt->a_stages));
CuAssertPtrNotNull(tc, buildingtypes);

stage = bt->a_stages;
CuAssertStrEquals(tc, "site", stage->name);
CuAssertIntEquals(tc, 2, stage->construction.maxsize);
CuAssertIntEquals(tc, SK_BUILDING, stage->construction.skill);

CuAssertPtrNotNull(tc, stage = stage->next);
stage = bt->a_stages + 1;
CuAssertPtrEquals(tc, NULL, stage->name);
CuAssertIntEquals(tc, 6, stage->construction.maxsize);
CuAssertIntEquals(tc, SK_BUILDING, stage->construction.skill);

CuAssertPtrNotNull(tc, stage = stage->next);
stage = bt->a_stages + 2;
CuAssertIntEquals(tc, -1, stage->construction.maxsize);
CuAssertIntEquals(tc, SK_SHIPBUILDING, stage->construction.skill);

CuAssertPtrEquals(tc, NULL, stage->next);

cJSON_Delete(json);
test_teardown();
}
Expand Down Expand Up @@ -493,9 +493,9 @@ static void test_buildings(CuTest * tc)
CuAssertIntEquals(tc, MTF_VARIABLE, bt->maintenance[0].flags);
CuAssertIntEquals(tc, 0, bt->maintenance[1].number);

CuAssertPtrNotNull(tc, bt->stages);
CuAssertPtrEquals(tc, NULL, bt->stages->next);
con = &bt->stages->construction;
CuAssertPtrNotNull(tc, bt->a_stages);
CuAssertIntEquals(tc, 1, (int) arrlen(bt->a_stages));
con = &bt->a_stages->construction;
CuAssertPtrNotNull(tc, con->materials);
CuAssertIntEquals(tc, 2, con->materials[0].number);
CuAssertPtrEquals(tc, (void *)get_resourcetype(R_STONE), (void *)con->materials[0].rtype);
Expand Down
89 changes: 47 additions & 42 deletions src/kernel/building.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include <storage.h>
#include <strings.h>

#include <stb_ds.h>

/* libc includes */
#include <assert.h>
#include <stdlib.h>
Expand Down Expand Up @@ -101,12 +103,13 @@ static void bt_register(building_type * btype)

static void free_buildingtype(void *ptr) {
building_type *btype = (building_type *)ptr;
while (btype->stages) {
building_stage *next = btype->stages->next;
free(btype->stages->name);
free(btype->stages);
btype->stages = next;
size_t s;
for (s = arrlen(btype->a_stages); s > 0; --s) {
building_stage *stage = btype->a_stages + s - 1;
free(stage->name);
}
arrfree(btype->a_stages);

free(btype->maintenance);
free(btype->_name);
free(btype);
Expand Down Expand Up @@ -184,15 +187,16 @@ const char *buildingtype(const building_type * btype, const building * b, int bs
}
}
}
if (btype->stages && btype->stages->name) {
const building_stage *stage;
if (btype->a_stages) {
size_t s, len = arrlen(btype->a_stages);
if (b) {
bsize = adjust_size(b, bsize);
}
for (stage = btype->stages; stage; stage = stage->next) {
for (s = 0; s != len; ++s) {
const building_stage *stage = btype->a_stages + s;
bsize -= stage->construction.maxsize;
if (!stage->next || bsize <0) {
return stage->name;
if (stage->construction.maxsize < 0 || bsize < 0) {
return stage->name ? stage->name : btype->_name;
}
}
}
Expand Down Expand Up @@ -423,10 +427,11 @@ building *new_building(const struct building_type * btype, region * r,

static int build_stages(unit *u, const building_type *btype, int built, int n, int basesk, int *skill_total) {

const building_stage *stage;
int made = 0;
size_t s, len = arrlen(btype->a_stages);

for (stage = btype->stages; stage; stage = stage->next) {
for (s = 0; s != len; ++s) {
const building_stage *stage = btype->a_stages + s;
const construction *con = &stage->construction;
if (con->maxsize < 0 || con->maxsize > built) {
int err, want = INT_MAX;
Expand Down Expand Up @@ -478,7 +483,7 @@ static int build_failure(unit *u, order *ord, const building_type *btype, int wa
break;
case ENOMATERIALS:
ADDMSG(&u->faction->msgs, msg_materials_required(u, ord,
&btype->stages->construction, want));
&btype->a_stages[0].construction, want));
break;
case ELOWSKILL:
case ENEEDSKILL:
Expand All @@ -502,7 +507,7 @@ build_building(unit *u, const building_type *btype, int id, int want, order *ord
int skills, basesk; /* number of skill points remainig */

assert(u->number);
assert(btype->stages);
assert(btype->a_stages);

basesk = effskill(u, SK_BUILDING, NULL);
skills = build_skill(u, basesk, 0, SK_BUILDING);
Expand Down Expand Up @@ -715,6 +720,34 @@ void free_buildings(void)

extern struct attrib_type at_icastle;

static int bt_effsize(const building_type *btype, const building *b, int bsize)
{
if (b) {
bsize = adjust_size(b, bsize);
}

if (btype && btype->a_stages) {
int n = 0;
size_t s, len = arrlen(btype->a_stages);
for (s = 0; s != len; ++s) {
const building_stage *stage = btype->a_stages + s;
const construction *con = &stage->construction;
if (con->maxsize < 0) {
break;
}
else {
if (bsize >= con->maxsize) {
bsize -= con->maxsize;
++n;
}
}
}
return n;
}

return 0;
}

/** returns the building's build stage (NOT size in people).
* only makes sense for castles or similar buildings with multiple
* stages */
Expand Down Expand Up @@ -747,34 +780,6 @@ const building_type *visible_building(const building *b) {
return b->type;
}

int bt_effsize(const building_type * btype, const building * b, int bsize)
{
if (b) {
bsize = adjust_size(b, bsize);
}

if (btype && btype->stages) {
int n = 0;
const building_stage *stage = btype->stages;
do {
const construction *con = &stage->construction;
if (con->maxsize < 0) {
break;
}
else {
if (bsize >= con->maxsize) {
bsize -= con->maxsize;
++n;
}
stage = stage->next;
}
} while (stage && bsize > 0);
return n;
}

return 0;
}

const char *write_buildingname(const building * b, char *ibuf, size_t size)
{
snprintf(ibuf, size, "%s (%s)", b->name, itoa36(b->no));
Expand Down
6 changes: 1 addition & 5 deletions src/kernel/building.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ extern "C" {
struct construction construction;
/* building stage name: */
char * name;
/* next stage, if upgradable: */
struct building_stage * next;
} building_stage;

typedef struct building_type {
Expand All @@ -62,7 +60,7 @@ extern "C" {
double auraregen; /* modifier for aura regeneration inside building */
struct maintenance *maintenance; /* array of requirements */
struct resource_mod *modifiers; /* modify production skills */
struct building_stage *stages;
struct building_stage *a_stages;
} building_type;

extern struct selist *buildingtypes;
Expand All @@ -74,8 +72,6 @@ extern "C" {
bool bt_changed(int *cache);
const building_type *bt_find(const char *name);
void free_buildingtypes(void);
int bt_effsize(const struct building_type *btype,
const struct building *b, int bsize);

bool in_safe_building(struct unit *u1, struct unit *u2);

Expand Down
Loading

0 comments on commit b24ee03

Please sign in to comment.