do not use floats for material-save.

abusing variants for storing short fractions.
remove unused RMF_SAVERESOURCE.
This commit is contained in:
Enno Rehling 2017-02-17 21:45:10 +01:00
parent ed94ef6d48
commit 2328975dc2
4 changed files with 32 additions and 22 deletions

View File

@ -863,7 +863,7 @@ static void manufacture(unit * u, const item_type * itype, int want)
typedef struct allocation { typedef struct allocation {
struct allocation *next; struct allocation *next;
int want, get; int want, get;
double save; variant save;
unsigned int flags; unsigned int flags;
unit *unit; unit *unit;
} allocation; } allocation;
@ -883,17 +883,18 @@ enum {
AFL_LOWSKILL = 1 << 1 AFL_LOWSKILL = 1 << 1
}; };
struct message * get_modifiers(unit *u, const resource_mod *mod, double *savep, int *skillp) { struct message * get_modifiers(unit *u, const resource_mod *mod, variant *savep, int *skillp) {
struct building *b = inside_building(u); struct building *b = inside_building(u);
const struct building_type *btype = building_is_active(b) ? b->type : NULL; const struct building_type *btype = building_is_active(b) ? b->type : NULL;
double save = 1.0; int save_n = 1, save_d = 1;
int skill = 0; int skill = 0;
for (; mod->flags != 0; ++mod) { for (; mod->flags != 0; ++mod) {
if (mod->btype == NULL || mod->btype == btype) { if (mod->btype == NULL || mod->btype == btype) {
if (mod->race == NULL || mod->race == u_race(u)) { if (mod->race == NULL || mod->race == u_race(u)) {
if (mod->flags & RMF_SAVEMATERIAL) { if (mod->flags & RMF_SAVEMATERIAL) {
save *= mod->value.f; save_n *= mod->value.sa[0];
save_d *= mod->value.sa[1];
} }
if (mod->flags & RMF_SKILL) { if (mod->flags & RMF_SKILL) {
skill += mod->value.i; skill += mod->value.i;
@ -904,7 +905,12 @@ struct message * get_modifiers(unit *u, const resource_mod *mod, double *savep,
} }
} }
*skillp = skill; *skillp = skill;
*savep = save; assert(save_n < SHRT_MAX);
assert(save_n > SHRT_MIN);
assert(save_d < SHRT_MAX);
assert(save_d > SHRT_MIN);
savep->sa[0] = (short)save_n;
savep->sa[1] = (short)save_d;
return NULL; return NULL;
} }
@ -919,7 +925,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
resource_limit *rdata = (resource_limit *)a->data.v; resource_limit *rdata = (resource_limit *)a->data.v;
const resource_type *rring; const resource_type *rring;
int amount, skill, skill_mod = 0; int amount, skill, skill_mod = 0;
double save_mod = 1.0; variant save_mod;
/* momentan kann man keine ressourcen abbauen, wenn man daf<61>r /* momentan kann man keine ressourcen abbauen, wenn man daf<61>r
* Materialverbrauch hat: */ * Materialverbrauch hat: */
@ -947,6 +953,10 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
return; return;
} }
} }
else {
save_mod.sa[0] = 1;
save_mod.sa[1] = 1;
}
/* Bergw<67>chter k<>nnen Abbau von Eisen/Laen durch Bewachen verhindern. /* Bergw<67>chter k<>nnen Abbau von Eisen/Laen durch Bewachen verhindern.
* Als magische Wesen 'sehen' Bergw<EFBFBD>chter alles und werden durch * Als magische Wesen 'sehen' Bergw<EFBFBD>chter alles und werden durch
@ -1023,9 +1033,9 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
alist->data = al; alist->data = al;
} }
static int required(int want, double save) static int required(int want, variant save)
{ {
int req = (int)(want * save); int req = (int)(want * save.sa[0] / save.sa[1]);
return req; return req;
} }
@ -1088,7 +1098,7 @@ leveled_allocation(const resource_type * rtype, region * r, allocation * alist)
use += x; use += x;
nreq -= want; nreq -= want;
need -= x; need -= x;
al->get = MIN(al->want, al->get + (int)(1 + x / al->save)); al->get = MIN(al->want, al->get + x * al->save.sa[1] / al->save.sa[0]);
} }
} }
if (use) { if (use) {
@ -1126,12 +1136,13 @@ attrib_allocation(const resource_type * rtype, region * r, allocation * alist)
if (avail > 0) { if (avail > 0) {
int want = required(al->want, al->save); int want = required(al->want, al->save);
int x = avail * want / nreq; int x = avail * want / nreq;
/* Wenn Rest, dann w<>rfeln, ob ich was bekomme: */ int rx = (avail * want) % nreq;
if (rng_int() % nreq < (avail * want) % nreq) /* Wenn Rest, dann wuerfeln, ob ich was bekomme: */
++x; if (rx>0 && rng_int() % nreq < rx) ++x;
avail -= x; avail -= x;
nreq -= want; nreq -= want;
al->get = MIN(al->want, (int)(x / al->save)); al->get = x * al->save.sa[0] / al->save.sa[1];
al->get = MIN(al->want, al->get);
if (rdata->produce) { if (rdata->produce) {
int use = required(al->get, al->save); int use = required(al->get, al->save);
if (use) if (use)
@ -2619,8 +2630,9 @@ expandwork(region * r, request * work_begin, request * work_end, int maxwork)
if (jobs >= working) if (jobs >= working)
workers = u->number; workers = u->number;
else { else {
int r = (u->number * jobs) % working;
workers = u->number * jobs / working; workers = u->number * jobs / working;
if (rng_int() % working < (u->number * jobs) % working) if (r > 0 && rng_int() % working < r)
workers++; workers++;
} }

View File

@ -350,6 +350,7 @@ static void test_make_item(CuTest *tc) {
resource_type *rtype; resource_type *rtype;
attrib *a; attrib *a;
resource_limit *rdata; resource_limit *rdata;
double d = 0.6;
test_setup(); test_setup();
init_resources(); init_resources();
@ -397,7 +398,8 @@ static void test_make_item(CuTest *tc) {
rdata->modifiers = calloc(2, sizeof(resource_mod)); rdata->modifiers = calloc(2, sizeof(resource_mod));
rdata->modifiers[0].flags = RMF_SAVEMATERIAL; rdata->modifiers[0].flags = RMF_SAVEMATERIAL;
rdata->modifiers[0].race = u->_race; rdata->modifiers[0].race = u->_race;
rdata->modifiers[0].value.f = (float)0.6; rdata->modifiers[0].value.sa[0] = (short)(0.5+100*d);
rdata->modifiers[0].value.sa[1] = 100;
make_item(u, itype, 10); make_item(u, itype, 10);
split_allocations(u->region); split_allocations(u->region);
CuAssertIntEquals(tc, 21, get_item(u, itype)); CuAssertIntEquals(tc, 21, get_item(u, itype));

View File

@ -91,8 +91,7 @@ extern "C" {
/* resource-limits for regions */ /* resource-limits for regions */
#define RMF_SKILL 0x01 /* int, bonus on resource production skill */ #define RMF_SKILL 0x01 /* int, bonus on resource production skill */
#define RMF_SAVEMATERIAL 0x02 /* float, multiplier on resource usage */ #define RMF_SAVEMATERIAL 0x02 /* fraction (sa[0]/sa[1]), multiplier on resource usage */
#define RMF_SAVERESOURCE 0x03 /* int, bonus on resource production skill */
#define RMF_REQUIREDBUILDING 0x04 /* building, required to build */ #define RMF_REQUIREDBUILDING 0x04 /* building, required to build */
typedef struct resource_mod { typedef struct resource_mod {

View File

@ -1025,13 +1025,10 @@ static int parse_resources(xmlDocPtr doc)
rdata->modifiers[k].flags = RMF_SKILL; rdata->modifiers[k].flags = RMF_SKILL;
} }
else if (strcmp((const char *)propValue, "material") == 0) { else if (strcmp((const char *)propValue, "material") == 0) {
rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0); rdata->modifiers[k].value.sa[0] = (short)(0.5+100*xml_fvalue(node, "value", 0));
rdata->modifiers[k].value.sa[1] = 100;
rdata->modifiers[k].flags = RMF_SAVEMATERIAL; rdata->modifiers[k].flags = RMF_SAVEMATERIAL;
} }
else if (strcmp((const char *)propValue, "resource") == 0) {
rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0);
rdata->modifiers[k].flags = RMF_SAVERESOURCE;
}
else if (strcmp((const char *)propValue, "require") == 0) { else if (strcmp((const char *)propValue, "require") == 0) {
xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building"); xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building");
if (propBldg != NULL) { if (propBldg != NULL) {