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
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
45
src/laws.c
45
src/laws.c
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue