fix counting of units, making it slower but more correct

This commit is contained in:
Enno Rehling 2014-05-24 20:25:06 -07:00
parent 649a43a27e
commit 7038b021de
7 changed files with 122 additions and 135 deletions

View file

@ -847,19 +847,16 @@ static int tolua_unit_get_race(lua_State * L)
static int tolua_unit_set_race(lua_State * L)
{
unit *self = (unit *) tolua_tousertype(L, 1, 0);
const char *rcname = tolua_tostring(L, 2, 0);
race *rc = rc_find(rcname);
if (rc != NULL) {
if (count_unit(self))
--self->faction->no_units;
if (self->irace == u_race(self))
self->irace = NULL;
u_setrace(self, rc);
if (count_unit(self))
--self->faction->no_units;
}
return 0;
unit *self = (unit *) tolua_tousertype(L, 1, 0);
const char *rcname = tolua_tostring(L, 2, 0);
race *rc = rc_find(rcname);
if (rc != NULL) {
if (self->irace == u_race(self)) {
self->irace = NULL;
}
u_setrace(self, rc);
}
return 0;
}
static int tolua_unit_destroy(lua_State * L)

View file

@ -1194,59 +1194,41 @@ void update_lighthouse(building * lh)
}
}
int count_all(const faction * f)
int count_faction(const faction * f, int flags)
{
#ifndef NDEBUG
unit *u;
int np = 0, n = 0;
int n = 0;
for (u = f->units; u; u = u->nextF) {
assert(f == u->faction);
n += u->number;
if (playerrace(u_race(u))) {
np += u->number;
const race *rc = u_race(u);
int x = (flags&COUNT_UNITS) ? 1 : u->number;
if (f->race!=rc) {
if (!playerrace(rc)) {
if (flags&COUNT_MONSTERS) {
n+=x;
}
} else if (flags&COUNT_MIGRANTS) {
if (!is_cursed(u->attribs, C_SLAVE, 0)) {
n+=x;
}
}
} else if (flags&COUNT_DEFAULT) {
n+=x;
}
}
if (f->num_people != np) {
log_error("# of people in %s is != num_people: %d should be %d.\n", factionid(f), f->num_people, np);
}
if (f->num_total != n) {
log_error("# of men in %s is != num_total: %d should be %d.\n", factionid(f), f->num_total, n);
}
#endif
return (f->flags & FFL_NPC) ? f->num_total : f->num_people;
return n;
}
int count_units(const faction * f)
{
#ifndef NDEBUG
unit *u;
int n = 0, np = 0;
for (u = f->units; u; u = u->nextF) {
++n;
if (playerrace(u_race(u))) ++np;
}
n = (f->flags & FFL_NPC) ? n : np;
if (f->no_units && n != f->no_units) {
log_warning("# of units in %s is != no_units: %d should be %d.\n", factionid(f), f->no_units, n);
}
#endif
return n;
return count_faction(f, COUNT_ALL|COUNT_UNITS);
}
int count_all(const faction * f)
{
return count_faction(f, COUNT_ALL);
}
int count_migrants(const faction * f)
{
unit *u = f->units;
int n = 0;
while (u) {
assert(u->faction == f);
if (u_race(u) != f->race && u_race(u) != new_race[RC_ILLUSION]
&& u_race(u) != new_race[RC_SPELL]
&& !!playerrace(u_race(u)) && !(is_cursed(u->attribs, C_SLAVE, 0))) {
n += u->number;
}
u = u->nextF;
}
return n;
return count_faction(f, COUNT_MIGRANTS);
}
int count_maxmigrants(const faction * f)

View file

@ -256,16 +256,23 @@ extern "C" {
extern int rule_alliance_limit(void);
extern int rule_faction_limit(void);
int count_units(const struct faction * f);
int count_all(const struct faction *f);
int count_migrants(const struct faction *f);
int count_maxmigrants(const struct faction *f);
#define COUNT_MONSTERS 0x01
#define COUNT_MIGRANTS 0x02
#define COUNT_DEFAULT 0x04
#define COUNT_ALL 0x07
#define COUNT_UNITS 0x10
int count_faction(const struct faction * f, int flags);
int count_migrants(const struct faction * f);
int count_maxmigrants(const struct faction * f);
int count_all(const struct faction * f);
int count_units(const struct faction * f);
extern bool has_limited_skills(const struct unit *u);
extern const struct race *findrace(const char *, const struct locale *);
bool has_limited_skills(const struct unit *u);
const struct race *findrace(const char *, const struct locale *);
int eff_stealth(const struct unit *u, const struct region *r);
int ispresent(const struct faction *f, const struct region *r);
int eff_stealth(const struct unit *u, const struct region *r);
int ispresent(const struct faction *f, const struct region *r);
int check_option(struct faction *f, int option);
extern void parse_kwd(keyword_t kword, int (*dofun) (struct unit *,
@ -450,11 +457,6 @@ extern "C" {
extern struct attrib_type at_guard;
extern void free_gamedata(void);
#if 1 /* disable to count all units */
# define count_unit(u) (u->number>0 && playerrace(u_race(u)))
#else
# define count_unit(u) 1
#endif
#ifdef __cplusplus
}

View file

@ -574,36 +574,50 @@ writeorder(struct gamedata *data, const struct order *ord,
unit *read_unit(struct gamedata *data)
{
unit *u;
int number, n, p;
order **orderp;
char obuf[DISPLAYSIZE];
faction *f;
char rname[32];
unit *u;
int number, n, p;
order **orderp;
char obuf[DISPLAYSIZE];
faction *f;
char rname[32];
READ_INT(data->store, &n);
if (n <= 0)
return NULL;
u = findunit(n);
if (u == NULL) {
u = calloc(sizeof(unit), 1);
u->no = n;
uhash(u);
} else {
while (u->attribs)
a_remove(&u->attribs, u->attribs);
while (u->items)
i_free(i_remove(&u->items, u->items));
free(u->skills);
u->skills = 0;
u->skill_size = 0;
u_setfaction(u, NULL);
}
READ_INT(data->store, &n);
if (n <= 0) {
log_error("data contains invalid unit %d.\n", n);
assert(n>0);
return 0;
}
u = findunit(n);
if (u) {
log_error("reading unit %s that already exists.\n", unitname(u));
while (u->attribs) {
a_remove(&u->attribs, u->attribs);
}
while (u->items) {
i_free(i_remove(&u->items, u->items));
}
free(u->skills);
u->skills = 0;
u->skill_size = 0;
u_setfaction(u, NULL);
} else {
u = calloc(sizeof(unit), 1);
u->no = n;
uhash(u);
}
READ_INT(data->store, &n);
f = findfaction(n);
if (f != u->faction)
u_setfaction(u, f);
READ_INT(data->store, &n);
f = findfaction(n);
if (f != u->faction) {
u_setfaction(u, f);
}
if (u->faction) {
++u->faction->no_units;
} else {
log_error("unit %s has faction == NULL\n", unitname(u));
assert(u->faction);
return 0;
}
READ_STR(data->store, obuf, sizeof(obuf));
u->name = _strdup(obuf);
@ -614,6 +628,11 @@ unit *read_unit(struct gamedata *data)
u->display = _strdup(obuf);
}
READ_INT(data->store, &number);
set_number(u, number);
READ_INT(data->store, &n);
u->age = (short)n;
@ -660,16 +679,6 @@ unit *read_unit(struct gamedata *data)
}
}
}
if (u->faction == NULL) {
log_error("unit %s has faction == NULL\n", unitname(u));
u_setfaction(u, get_monsters());
set_number(u, 0);
}
if (count_unit(u) && u->faction)
u->faction->no_units++;
set_number(u, number);
READ_INT(data->store, &n);
if (n > 0) {

View file

@ -1074,9 +1074,7 @@ void u_setfaction(unit * u, faction * f)
if (u->faction == f)
return;
if (u->faction) {
if (count_unit(u)) {
--u->faction->no_units;
}
--u->faction->no_units;
set_number(u, 0);
join_group(u, NULL);
free_orders(&u->orders);
@ -1112,7 +1110,7 @@ void u_setfaction(unit * u, faction * f)
if (cnt) {
set_number(u, cnt);
}
if (f && count_unit(u)) {
if (f) {
++f->no_units;
}
}
@ -1126,7 +1124,7 @@ void set_number(unit * u, int count)
if (count == 0) {
u->flags &= ~(UFL_HERO);
}
if (u->faction && playerrace(u_race(u))) {
if (u->faction) {
u->faction->num_people += count - u->number;
}
u->number = (unsigned short)count;

View file

@ -3482,33 +3482,32 @@ static int maxunits(const faction * f)
int checkunitnumber(const faction * f, int add)
{
int alimit, flimit;
alimit = rule_alliance_limit();
if (alimit) {
/* if unitsperalliance is true, maxunits returns the
number of units allowed in an alliance */
faction *f2;
int unitsinalliance = add;
for (f2 = factions; f2; f2 = f2->next) {
if (f->alliance == f2->alliance) {
unitsinalliance += f2->no_units;
}
if (unitsinalliance > alimit) {
return 1;
}
int alimit, flimit;
int flags = COUNT_DEFAULT|COUNT_MIGRANTS|COUNT_UNITS;
int fno = count_faction(f, flags) + add;
flimit = rule_faction_limit();
if (flimit && fno > flimit) {
return 2;
}
}
flimit = rule_faction_limit();
if (flimit) {
if (f->no_units + add > flimit) {
return 2;
alimit = rule_alliance_limit();
if (alimit) {
/* if unitsperalliance is true, maxunits returns the
number of units allowed in an alliance */
faction *f2;
int unitsinalliance = fno;
for (f2 = factions; f2; f2 = f2->next) {
if (f != f2 && f->alliance == f2->alliance) {
unitsinalliance += count_faction(f2, flags);
if (unitsinalliance > alimit) {
return 1;
}
}
}
}
}
return 0;
return 0;
}
void new_units(void)

View file

@ -93,11 +93,11 @@ static void out_faction(FILE * file, const struct faction *f)
fprintf(file, "%s (%s/%d) (%.3s/%.3s), %d Einh., %d Pers., $%d, %d NMR\n",
f->name, itoa36(f->no), f_get_alliance(f) ? f->alliance->id : 0,
LOC(default_locale, rc_name(f->race, 0)), magic_school[f->magiegebiet],
f->no_units, f->num_total, f->money, turn - f->lastorders);
count_units(f), f->num_total, f->money, turn - f->lastorders);
} else {
fprintf(file, "%s (%.3s/%.3s), %d Einh., %d Pers., $%d, %d NMR\n",
factionname(f), LOC(default_locale, rc_name(f->race, 0)),
magic_school[f->magiegebiet], f->no_units, f->num_total, f->money,
magic_school[f->magiegebiet], count_units(f), f->num_total, f->money,
turn - f->lastorders);
}
}