From b80fd4e982b966194114b2e93f66398bf476fd3d Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 1 Jun 2016 21:35:24 +0200 Subject: [PATCH] update neweff production: Limit work in big cities Civilians, military and uw work only up to their sector's population limit. The population limit depends on the sector type's maximum population, research if RES_POP is enabled, and the sector's efficiency for big cities. The population limit may decrease between computation of work in do_feed() and the end of the update: * Research declines (only relevant with RES_POP). Work is not corrected. The declined research will apply at the next update. Since levels age after production is done, any work corrections could only affect leftover available work. Wouldn't make sense. The effect is negligible anyway. Even with an insanely fast decline of 60% (level_age_rate = 1, etu_per_update = 60), the population limit decreases by less than 10% in the worst case. * upd_buildeff() changes sector type and efficiency. Work is corrected only when this changes the sector type from big city to not big city. It isn't corrected on other sector type changes. These can affect maximum population since the sector type's maximum became configurable in commit 153527a (v4.2.20). Sane configurations don't let players redesignate sectors to a type with different maximum population. The server doesn't enforce this, though. It isn't corrected when a big city's efficiency decreases, but sector type change isn't achieved. Harmless, because tearing down a city takes very little work (25 for 100%), so efficiency decrease without type change means the work we have must be safely below any sane population limit's work. Good enough. However, the code implementing the work correction for big cities is unclean. Get rid of it by tweaking the rules: a big city's extra population does not work. City slickers, tsk, tsk, tsk. At least they still pay their taxes. Signed-off-by: Markus Armbruster --- include/prototypes.h | 1 + src/lib/commands/newe.c | 7 ++++--- src/lib/commands/prod.c | 20 +++++--------------- src/lib/common/res_pop.c | 7 +++++++ src/lib/update/human.c | 8 ++++---- src/lib/update/populace.c | 15 ++++++++------- src/lib/update/sect.c | 16 +++++----------- tests/update/final.xdump | 2 +- tests/update/journal.log | 2 +- 9 files changed, 36 insertions(+), 42 deletions(-) diff --git a/include/prototypes.h b/include/prototypes.h index 389f3066..600e321f 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -270,6 +270,7 @@ extern int read_schedule(char *, time_t[], int, time_t, time_t); /* res_pop.c */ extern int max_population(float, int, int); extern int max_pop(float, struct sctstr *); +extern int max_workers(float, struct sctstr *); /* stmtch.c */ /* in match.h */ /* type.c */ diff --git a/src/lib/commands/newe.c b/src/lib/commands/newe.c index 6951e25e..04cc24a6 100644 --- a/src/lib/commands/newe.c +++ b/src/lib/commands/newe.c @@ -28,6 +28,7 @@ * * Known contributors to this file: * Thomas Ruschak, 1993 + * Markus Armbruster, 2004-2016 */ #include @@ -50,7 +51,7 @@ newe(void) int twork; int type; int eff; - int maxpop; + int maxworkers; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; @@ -64,11 +65,11 @@ newe(void) civs = (1.0 + obrate * etu_per_update) * sect.sct_item[I_CIVIL]; uws = (1.0 + uwbrate * etu_per_update) * sect.sct_item[I_UW]; natp = getnatp(sect.sct_own); - maxpop = max_pop(natp->nat_level[NAT_RLEV], §); + maxworkers = max_workers(natp->nat_level[NAT_RLEV], §); work = new_work(§, total_work(sect.sct_work, etu_per_update, civs, sect.sct_item[I_MILIT], uws, - maxpop)); + maxworkers)); bwork = work / 2; type = sect.sct_type; diff --git a/src/lib/commands/prod.c b/src/lib/commands/prod.c index 0b1d5469..2f552710 100644 --- a/src/lib/commands/prod.c +++ b/src/lib/commands/prod.c @@ -29,7 +29,7 @@ * Known contributors to this file: * David Muir Sharnoff, 1987 * Steve McClure, 1997-2000 - * Markus Armbruster, 2004-2013 + * Markus Armbruster, 2004-2016 */ #include @@ -95,8 +95,7 @@ prod(void) int twork; int type; int eff; - int maxpop; - int otype; + int maxworkers; char mnem; if (!snxtsct(&nstr, player->argp[1])) @@ -111,12 +110,12 @@ prod(void) civs = (1.0 + obrate * etu_per_update) * sect.sct_item[I_CIVIL]; uws = (1.0 + uwbrate * etu_per_update) * sect.sct_item[I_UW]; natp = getnatp(sect.sct_own); - maxpop = max_pop(natp->nat_level[NAT_RLEV], §); + maxworkers = max_workers(natp->nat_level[NAT_RLEV], §); work = new_work(§, total_work(sect.sct_work, etu_per_update, civs, sect.sct_item[I_MILIT], uws, - maxpop)); + maxworkers)); bwork = work / 2; if (sect.sct_off) @@ -130,20 +129,10 @@ prod(void) } bwork -= twork; eff -= twork * 4; - otype = type; if (eff <= 0) { type = sect.sct_newtype; eff = 0; } - if (!eff && IS_BIG_CITY(otype) && !IS_BIG_CITY(type)) { - maxpop = max_population(natp->nat_level[NAT_RLEV], - type, eff); - work = new_work(§, - total_work(sect.sct_work, etu_per_update, - civs, sect.sct_item[I_MILIT], - uws, maxpop)); - bwork = MIN(work / 2, bwork); - } twork = 100 - eff; if (twork > bwork) { twork = bwork; @@ -175,6 +164,7 @@ prod(void) continue; if (type == SCT_ENLIST) { + int maxpop = max_pop(natp->nat_level[NAT_RLEV], §); int maxmil; int enlisted; diff --git a/src/lib/common/res_pop.c b/src/lib/common/res_pop.c index 91fcb89f..4034965a 100644 --- a/src/lib/common/res_pop.c +++ b/src/lib/common/res_pop.c @@ -29,6 +29,7 @@ * Known contributors to this file: * Ken Stevens, 1995 * Steve McClure, 1998 + * Markus Armbruster, 2005-2016 */ #include @@ -71,3 +72,9 @@ max_pop(float research, struct sctstr *sp) { return max_population(research, sp->sct_type, sp->sct_effic); } + +int +max_workers(float research, struct sctstr *sp) +{ + return max_population(research, sp->sct_type, 0); +} diff --git a/src/lib/update/human.c b/src/lib/update/human.c index 8f606e87..5acb18cc 100644 --- a/src/lib/update/human.c +++ b/src/lib/update/human.c @@ -29,7 +29,7 @@ * Known contributors to this file: * Dave Pare, 1986 * Steve McClure, 1996 - * Markus Armbruster, 2004-2012 + * Markus Armbruster, 2004-2016 */ #include @@ -59,17 +59,17 @@ do_feed(struct sctstr *sp, struct natstr *np, short *vec, int work_avail; int starved, sctwork; int needed; - int maxpop; + int maxworkers; int manna; /* grow people & stuff */ sctwork = sp->sct_work; - maxpop = max_pop(np->nat_level[NAT_RLEV], sp); + maxworkers = max_workers(np->nat_level[NAT_RLEV], sp); work_avail = new_work(sp, total_work(sctwork, etu, vec[I_CIVIL], vec[I_MILIT], vec[I_UW], - maxpop)); + maxworkers)); if (sp->sct_type != SCT_SANCT) { manna = 0; diff --git a/src/lib/update/populace.c b/src/lib/update/populace.c index 0f3e2afc..04c501bb 100644 --- a/src/lib/update/populace.c +++ b/src/lib/update/populace.c @@ -115,14 +115,15 @@ populace(struct natstr *np, struct sctstr *sp, int etu) } int -total_work(int sctwork, int etu, int civil, int milit, int uw, int maxpop) +total_work(int sctwork, int etu, int civil, int milit, int uw, + int maxworkers) { - if (civil > maxpop) - civil = maxpop; - if (milit > maxpop) - milit = maxpop; - if (uw > maxpop) - uw = maxpop; + if (civil > maxworkers) + civil = maxworkers; + if (milit > maxworkers) + milit = maxworkers; + if (uw > maxworkers) + uw = maxworkers; return (civil * sctwork / 100.0 + milit / 2.5 + uw) * etu / 100.0; } diff --git a/src/lib/update/sect.c b/src/lib/update/sect.c index 4251e65b..1249cf22 100644 --- a/src/lib/update/sect.c +++ b/src/lib/update/sect.c @@ -51,7 +51,7 @@ */ static int upd_buildeff(struct natstr *np, struct sctstr *sp, int *workp, - short *vec, int etu, int *desig, int sctwork, int *cost) + short *vec, int etu, int *desig, int *cost) { int work_cost = 0; int buildeff_work = *workp / 2; @@ -78,17 +78,12 @@ upd_buildeff(struct natstr *np, struct sctstr *sp, int *workp, neweff = n; *cost += work_cost; if (!n && IS_BIG_CITY(old_type) && !IS_BIG_CITY(*desig)) { - /* FIXME use trunc_people() and total_work() */ + /* FIXME use trunc_people() */ int maxpop = max_population(np->nat_level[NAT_RLEV], *desig, n); if (vec[I_CIVIL] > maxpop) vec[I_CIVIL] = maxpop; if (vec[I_UW] > maxpop) vec[I_UW] = maxpop; - *workp = (vec[I_CIVIL] * sctwork) / 100.0 - + (vec[I_MILIT] * 2 / 5.0) + vec[I_UW]; - *workp = roundavg((etu * *workp) / 100.0); - - buildeff_work = MIN((int)(*workp / 2), buildeff_work); } } if (*desig == sp->sct_newtype) { @@ -262,7 +257,7 @@ produce_sect(int natnum, int etu, struct bp *bp, int p_sect[][2]) struct natstr *np; short buf[I_MAX + 1]; short *vec; - int work, cost, ecost, pcost, sctwork; + int work, cost, ecost, pcost; int n, desig, neweff, amount; for (n = 0; NULL != (sp = getsectid(n)); n++) { @@ -307,7 +302,7 @@ produce_sect(int natnum, int etu, struct bp *bp, int p_sect[][2]) sp->sct_updated = 1; work = 0; - sctwork = do_feed(sp, np, vec, &work, etu); + do_feed(sp, np, vec, &work, etu); bp_put_items(bp, sp, vec); if (sp->sct_off || np->nat_money < 0) @@ -329,8 +324,7 @@ produce_sect(int natnum, int etu, struct bp *bp, int p_sect[][2]) if ((sp->sct_effic < 100 || sp->sct_type != sp->sct_newtype) && np->nat_money >= 0) { - neweff = upd_buildeff(np, sp, &work, vec, etu, &desig, sctwork, - &cost); + neweff = upd_buildeff(np, sp, &work, vec, etu, &desig, &cost); bp_put_items(bp, sp, vec); p_sect[SCT_EFFIC][0]++; p_sect[SCT_EFFIC][1] += cost; diff --git a/tests/update/final.xdump b/tests/update/final.xdump index 16b8e98d..c950c1ab 100644 --- a/tests/update/final.xdump +++ b/tests/update/final.xdump @@ -259,7 +259,7 @@ owner xloc yloc des effic mobil off loyal terr0 terr1 terr2 terr3 dterr xdist yd 4 -6 -2 4 39 120 0 0 0 0 0 0 0 -6 -2 39 0 100 0 4 0 0 0 0 0 4 130 0 0 0 0 0 0 0 97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 0 0 0 0 0 0 0 4 -4 -2 4 39 120 0 0 0 0 0 0 0 -4 -2 39 0 100 0 4 0 0 0 0 0 4 130 0 0 0 0 0 0 0 97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 0 0 0 0 0 0 0 4 -2 -2 4 39 120 0 0 0 0 0 0 0 -2 -2 39 0 100 0 4 0 0 0 0 0 4 130 0 0 0 0 0 0 0 97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 0 0 0 0 0 0 0 -3 1 -1 5 100 120 0 0 0 0 0 0 0 1 -1 5999 0 100 0 5 0 0 0 0 0 3 9999 0 0 0 0 0 0 0 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 0 0 0 0 0 0 0 +3 1 -1 5 100 120 0 0 0 0 0 0 0 1 -1 600 0 100 0 5 0 0 0 0 0 3 9999 0 0 0 0 0 0 0 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 0 0 0 0 0 0 0 3 3 -1 4 39 120 0 0 0 0 0 0 0 3 -1 39 0 100 0 4 0 0 0 0 0 3 130 0 0 0 0 0 0 0 97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 0 0 0 0 0 0 0 3 5 -1 6 100 120 0 0 0 0 0 0 0 5 -1 0 0 100 0 6 0 0 0 0 73 3 130 0 0 0 0 0 0 0 96 0 0 0 0 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 0 0 0 0 0 0 0 3 7 -1 4 39 120 0 0 0 0 0 0 0 7 -1 39 0 100 0 4 0 0 0 0 0 3 130 0 0 0 0 0 0 0 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 0 0 0 0 0 0 0 diff --git a/tests/update/journal.log b/tests/update/journal.log index 200259a6..cd036c98 100644 --- a/tests/update/journal.log +++ b/tests/update/journal.log @@ -1163,7 +1163,7 @@ Play#0 output Play#0 1 3 10,-2 w 14% 120 .. .. 130 0 0 97 100% 39 0 Play#0 output Play#0 1 3 12,-2 - 39% 120 .. .. 130 0 0 97 100% 39 0 Play#0 output Play#0 1 3 14,-2 - 39% 120 .. .. 130 0 0 96 100% 39 0 1 - Play#0 output Play#0 1 3 1,-1 c 100% 120 .. .. 9999 0 0 100 100% 5999 0 + Play#0 output Play#0 1 3 1,-1 c 100% 120 .. .. 9999 0 0 100 100% 600 0 Play#0 output Play#0 1 3 3,-1 - 39% 120 .. .. 130 0 0 97 100% 39 0 Play#0 output Play#0 1 3 5,-1 u 100% 120 .. .. 130 0 0 96 100% 0 0 Play#0 output Play#0 1 3 7,-1 - 39% 120 .. .. 130 0 0 96 100% 39 0