forked from github/server
fix counting of units, making it slower but more correct
This commit is contained in:
parent
649a43a27e
commit
7038b021de
7 changed files with 122 additions and 135 deletions
|
@ -851,13 +851,10 @@ static int tolua_unit_set_race(lua_State * L)
|
||||||
const char *rcname = tolua_tostring(L, 2, 0);
|
const char *rcname = tolua_tostring(L, 2, 0);
|
||||||
race *rc = rc_find(rcname);
|
race *rc = rc_find(rcname);
|
||||||
if (rc != NULL) {
|
if (rc != NULL) {
|
||||||
if (count_unit(self))
|
if (self->irace == u_race(self)) {
|
||||||
--self->faction->no_units;
|
|
||||||
if (self->irace == u_race(self))
|
|
||||||
self->irace = NULL;
|
self->irace = NULL;
|
||||||
|
}
|
||||||
u_setrace(self, rc);
|
u_setrace(self, rc);
|
||||||
if (count_unit(self))
|
|
||||||
--self->faction->no_units;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
unit *u;
|
||||||
int np = 0, n = 0;
|
int n = 0;
|
||||||
for (u = f->units; u; u = u->nextF) {
|
for (u = f->units; u; u = u->nextF) {
|
||||||
assert(f == u->faction);
|
const race *rc = u_race(u);
|
||||||
n += u->number;
|
int x = (flags&COUNT_UNITS) ? 1 : u->number;
|
||||||
if (playerrace(u_race(u))) {
|
if (f->race!=rc) {
|
||||||
np += u->number;
|
if (!playerrace(rc)) {
|
||||||
|
if (flags&COUNT_MONSTERS) {
|
||||||
|
n+=x;
|
||||||
|
}
|
||||||
|
} else if (flags&COUNT_MIGRANTS) {
|
||||||
|
if (!is_cursed(u->attribs, C_SLAVE, 0)) {
|
||||||
|
n+=x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (f->num_people != np) {
|
} else if (flags&COUNT_DEFAULT) {
|
||||||
log_error("# of people in %s is != num_people: %d should be %d.\n", factionid(f), f->num_people, np);
|
n+=x;
|
||||||
}
|
}
|
||||||
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 n;
|
||||||
return (f->flags & FFL_NPC) ? f->num_total : f->num_people;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int count_units(const faction * f)
|
int count_units(const faction * f)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
return count_faction(f, COUNT_ALL|COUNT_UNITS);
|
||||||
unit *u;
|
}
|
||||||
int n = 0, np = 0;
|
int count_all(const faction * f)
|
||||||
for (u = f->units; u; u = u->nextF) {
|
{
|
||||||
++n;
|
return count_faction(f, COUNT_ALL);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int count_migrants(const faction * f)
|
int count_migrants(const faction * f)
|
||||||
{
|
{
|
||||||
unit *u = f->units;
|
return count_faction(f, COUNT_MIGRANTS);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int count_maxmigrants(const faction * f)
|
int count_maxmigrants(const faction * f)
|
||||||
|
|
|
@ -256,13 +256,20 @@ extern "C" {
|
||||||
extern int rule_alliance_limit(void);
|
extern int rule_alliance_limit(void);
|
||||||
extern int rule_faction_limit(void);
|
extern int rule_faction_limit(void);
|
||||||
|
|
||||||
int count_units(const struct faction * f);
|
#define COUNT_MONSTERS 0x01
|
||||||
int count_all(const struct faction *f);
|
#define COUNT_MIGRANTS 0x02
|
||||||
int count_migrants(const struct faction *f);
|
#define COUNT_DEFAULT 0x04
|
||||||
int count_maxmigrants(const struct faction *f);
|
#define COUNT_ALL 0x07
|
||||||
|
#define COUNT_UNITS 0x10
|
||||||
|
|
||||||
extern bool has_limited_skills(const struct unit *u);
|
int count_faction(const struct faction * f, int flags);
|
||||||
extern const struct race *findrace(const char *, const struct locale *);
|
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);
|
||||||
|
|
||||||
|
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 eff_stealth(const struct unit *u, const struct region *r);
|
||||||
int ispresent(const struct faction *f, const struct region *r);
|
int ispresent(const struct faction *f, const struct region *r);
|
||||||
|
@ -450,11 +457,6 @@ extern "C" {
|
||||||
|
|
||||||
extern struct attrib_type at_guard;
|
extern struct attrib_type at_guard;
|
||||||
extern void free_gamedata(void);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -582,28 +582,42 @@ unit *read_unit(struct gamedata *data)
|
||||||
char rname[32];
|
char rname[32];
|
||||||
|
|
||||||
READ_INT(data->store, &n);
|
READ_INT(data->store, &n);
|
||||||
if (n <= 0)
|
if (n <= 0) {
|
||||||
return NULL;
|
log_error("data contains invalid unit %d.\n", n);
|
||||||
|
assert(n>0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
u = findunit(n);
|
u = findunit(n);
|
||||||
if (u == NULL) {
|
if (u) {
|
||||||
u = calloc(sizeof(unit), 1);
|
log_error("reading unit %s that already exists.\n", unitname(u));
|
||||||
u->no = n;
|
while (u->attribs) {
|
||||||
uhash(u);
|
|
||||||
} else {
|
|
||||||
while (u->attribs)
|
|
||||||
a_remove(&u->attribs, u->attribs);
|
a_remove(&u->attribs, u->attribs);
|
||||||
while (u->items)
|
}
|
||||||
|
while (u->items) {
|
||||||
i_free(i_remove(&u->items, u->items));
|
i_free(i_remove(&u->items, u->items));
|
||||||
|
}
|
||||||
free(u->skills);
|
free(u->skills);
|
||||||
u->skills = 0;
|
u->skills = 0;
|
||||||
u->skill_size = 0;
|
u->skill_size = 0;
|
||||||
u_setfaction(u, NULL);
|
u_setfaction(u, NULL);
|
||||||
|
} else {
|
||||||
|
u = calloc(sizeof(unit), 1);
|
||||||
|
u->no = n;
|
||||||
|
uhash(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
READ_INT(data->store, &n);
|
READ_INT(data->store, &n);
|
||||||
f = findfaction(n);
|
f = findfaction(n);
|
||||||
if (f != u->faction)
|
if (f != u->faction) {
|
||||||
u_setfaction(u, f);
|
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));
|
READ_STR(data->store, obuf, sizeof(obuf));
|
||||||
u->name = _strdup(obuf);
|
u->name = _strdup(obuf);
|
||||||
|
@ -614,6 +628,11 @@ unit *read_unit(struct gamedata *data)
|
||||||
u->display = _strdup(obuf);
|
u->display = _strdup(obuf);
|
||||||
}
|
}
|
||||||
READ_INT(data->store, &number);
|
READ_INT(data->store, &number);
|
||||||
|
set_number(u, number);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
READ_INT(data->store, &n);
|
READ_INT(data->store, &n);
|
||||||
u->age = (short)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);
|
READ_INT(data->store, &n);
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
|
|
|
@ -1074,9 +1074,7 @@ void u_setfaction(unit * u, faction * f)
|
||||||
if (u->faction == f)
|
if (u->faction == f)
|
||||||
return;
|
return;
|
||||||
if (u->faction) {
|
if (u->faction) {
|
||||||
if (count_unit(u)) {
|
|
||||||
--u->faction->no_units;
|
--u->faction->no_units;
|
||||||
}
|
|
||||||
set_number(u, 0);
|
set_number(u, 0);
|
||||||
join_group(u, NULL);
|
join_group(u, NULL);
|
||||||
free_orders(&u->orders);
|
free_orders(&u->orders);
|
||||||
|
@ -1112,7 +1110,7 @@ void u_setfaction(unit * u, faction * f)
|
||||||
if (cnt) {
|
if (cnt) {
|
||||||
set_number(u, cnt);
|
set_number(u, cnt);
|
||||||
}
|
}
|
||||||
if (f && count_unit(u)) {
|
if (f) {
|
||||||
++f->no_units;
|
++f->no_units;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1126,7 +1124,7 @@ void set_number(unit * u, int count)
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
u->flags &= ~(UFL_HERO);
|
u->flags &= ~(UFL_HERO);
|
||||||
}
|
}
|
||||||
if (u->faction && playerrace(u_race(u))) {
|
if (u->faction) {
|
||||||
u->faction->num_people += count - u->number;
|
u->faction->num_people += count - u->number;
|
||||||
}
|
}
|
||||||
u->number = (unsigned short)count;
|
u->number = (unsigned short)count;
|
||||||
|
|
19
src/laws.c
19
src/laws.c
|
@ -3483,29 +3483,28 @@ static int maxunits(const faction * f)
|
||||||
int checkunitnumber(const faction * f, int add)
|
int checkunitnumber(const faction * f, int add)
|
||||||
{
|
{
|
||||||
int alimit, flimit;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
alimit = rule_alliance_limit();
|
alimit = rule_alliance_limit();
|
||||||
if (alimit) {
|
if (alimit) {
|
||||||
/* if unitsperalliance is true, maxunits returns the
|
/* if unitsperalliance is true, maxunits returns the
|
||||||
number of units allowed in an alliance */
|
number of units allowed in an alliance */
|
||||||
faction *f2;
|
faction *f2;
|
||||||
int unitsinalliance = add;
|
int unitsinalliance = fno;
|
||||||
|
|
||||||
for (f2 = factions; f2; f2 = f2->next) {
|
for (f2 = factions; f2; f2 = f2->next) {
|
||||||
if (f->alliance == f2->alliance) {
|
if (f != f2 && f->alliance == f2->alliance) {
|
||||||
unitsinalliance += f2->no_units;
|
unitsinalliance += count_faction(f2, flags);
|
||||||
}
|
|
||||||
if (unitsinalliance > alimit) {
|
if (unitsinalliance > alimit) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flimit = rule_faction_limit();
|
|
||||||
if (flimit) {
|
|
||||||
if (f->no_units + add > flimit) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -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",
|
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,
|
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],
|
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 {
|
} else {
|
||||||
fprintf(file, "%s (%.3s/%.3s), %d Einh., %d Pers., $%d, %d NMR\n",
|
fprintf(file, "%s (%.3s/%.3s), %d Einh., %d Pers., $%d, %d NMR\n",
|
||||||
factionname(f), LOC(default_locale, rc_name(f->race, 0)),
|
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);
|
turn - f->lastorders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue