From 41a2f7d1df923b8742785784a8e66d034b93012d Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 4 Jun 2016 09:50:09 +0200 Subject: [PATCH] neweff production: Consider insufficient food newe() and prod() duplicate parts of the update's do_feed(), except they round babies down instead of randomly, to get a stable, conservative forecast. Unlike the update, they assume sufficient food. Inaccurate for sectors that are going to starve or have suboptimal population growth. Not documented. Has always been that way. Eliminate the undocumented assumption by replacing the duplicate code by a call of do_feed(). Add a suitable parameter to do_feed() to preserve the different rounding. The update test shows the improvement. Signed-off-by: Markus Armbruster --- include/prototypes.h | 3 +-- src/lib/commands/newe.c | 11 +--------- src/lib/commands/prod.c | 23 ++++++--------------- src/lib/update/human.c | 43 ++++++++++++++++++++++------------------ src/lib/update/sect.c | 2 +- tests/update/journal.log | 14 ++++++------- 6 files changed, 40 insertions(+), 56 deletions(-) diff --git a/include/prototypes.h b/include/prototypes.h index 564ace37..2d6576c6 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -663,8 +663,7 @@ extern int dodistribute(struct sctstr *, int, double); /* finish.c */ extern void finish_sects(int); /* human.c */ -extern int new_work(struct sctstr *, int); -extern int do_feed(struct sctstr *, struct natstr *, int); +extern int do_feed(struct sctstr *, struct natstr *, int, int); extern int feed_people(short *, int); extern double food_needed(short *, int); extern int famine_victims(short *, int); diff --git a/src/lib/commands/newe.c b/src/lib/commands/newe.c index 04cc24a6..5351c78e 100644 --- a/src/lib/commands/newe.c +++ b/src/lib/commands/newe.c @@ -45,13 +45,10 @@ newe(void) struct nstr_sect nstr; double work, lcms, hcms; int nsect; - int civs = 0; - int uws = 0; int bwork; int twork; int type; int eff; - int maxworkers; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; @@ -62,14 +59,8 @@ newe(void) if (!player->owner) continue; if (!sect.sct_off) { - 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); - 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, - maxworkers)); + work = do_feed(§, natp, etu_per_update, 1); bwork = work / 2; type = sect.sct_type; diff --git a/src/lib/commands/prod.c b/src/lib/commands/prod.c index 2f552710..60ed59aa 100644 --- a/src/lib/commands/prod.c +++ b/src/lib/commands/prod.c @@ -89,13 +89,10 @@ prod(void) char cmnem[MAXPRCON]; int cuse[MAXPRCON], cmax[MAXPRCON]; int lcms, hcms; - int civs; - int uws; int bwork; int twork; int type; int eff; - int maxworkers; char mnem; if (!snxtsct(&nstr, player->argp[1])) @@ -106,20 +103,13 @@ prod(void) while (nxtsct(&nstr, §)) { if (!player->owner) continue; - - 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); - 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, - maxworkers)); - bwork = work / 2; - if (sect.sct_off) continue; + + natp = getnatp(sect.sct_own); + work = do_feed(§, natp, etu_per_update, 1); + bwork = work / 2; + type = sect.sct_type; eff = sect.sct_effic; if (sect.sct_newtype != type) { @@ -164,14 +154,13 @@ prod(void) continue; if (type == SCT_ENLIST) { - int maxpop = max_pop(natp->nat_level[NAT_RLEV], §); int maxmil; int enlisted; if (sect.sct_own != sect.sct_oldown) continue; enlisted = 0; - maxmil = MIN(civs, maxpop) / 2 - sect.sct_item[I_MILIT]; + maxmil = sect.sct_item[I_CIVIL] / 2 - sect.sct_item[I_MILIT]; if (maxmil > 0) { enlisted = (etu_per_update * (10 + sect.sct_item[I_MILIT]) diff --git a/src/lib/update/human.c b/src/lib/update/human.c index e05aa6b8..f8eef410 100644 --- a/src/lib/update/human.c +++ b/src/lib/update/human.c @@ -42,17 +42,19 @@ #include "update.h" #include "xy.h" +static int new_work(struct sctstr *, int); static int growfood(struct sctstr *, int, int); static int starve_some(short *, i_type, int); static void trunc_people(struct sctstr *, struct natstr *); -static int grow_people(struct sctstr *, int, struct natstr *); -static int babies(int, int, double, int, int); +static int grow_people(struct sctstr *, int, struct natstr *, int); +static int babies(int, int, double, int, int, int); /* * feed the individual sector */ int -do_feed(struct sctstr *sp, struct natstr *np, int etu) +do_feed(struct sctstr *sp, struct natstr *np, int etu, + int round_babies_down) { int work_avail; int starved, sctwork; @@ -67,7 +69,6 @@ do_feed(struct sctstr *sp, struct natstr *np, int etu) sp->sct_item[I_MILIT], sp->sct_item[I_UW], maxworkers)); - if (sp->sct_type != SCT_SANCT) { manna = 0; if (opt_NOFOOD == 0) { @@ -100,7 +101,7 @@ do_feed(struct sctstr *sp, struct natstr *np, int etu) sctwork += 7 + roll(15); if (sctwork > 100) sctwork = 100; - grow_people(sp, etu, np); + grow_people(sp, etu, np, round_babies_down); work_avail = new_work(sp, total_work(sp->sct_work, etu, sp->sct_item[I_CIVIL], @@ -124,7 +125,7 @@ do_feed(struct sctstr *sp, struct natstr *np, int etu) return work_avail; } -int +static int new_work(struct sctstr *sp, int delta) { if (sp->sct_type == sp->sct_newtype) @@ -231,17 +232,17 @@ trunc_people(struct sctstr *sp, struct natstr *np) * production? Maybe with just high education? */ static int -grow_people(struct sctstr *sp, int etu, struct natstr *np) +grow_people(struct sctstr *sp, int etu, struct natstr *np, int round_down) { int newciv; int newuw; int maxpop = max_pop(np->nat_level[NAT_RLEV], sp); newciv = babies(sp->sct_item[I_CIVIL], etu, obrate, - sp->sct_item[I_FOOD], maxpop); + sp->sct_item[I_FOOD], maxpop, round_down); sp->sct_item[I_CIVIL] += newciv; newuw = babies(sp->sct_item[I_UW], etu, uwbrate, - sp->sct_item[I_FOOD], maxpop); + sp->sct_item[I_FOOD], maxpop, round_down); sp->sct_item[I_UW] += newuw; /* * subtract the baby eat food (if we are using FOOD) and return @@ -257,24 +258,28 @@ grow_people(struct sctstr *sp, int etu, struct natstr *np) * @brate is the birth rate. * @food is the food available for growing babies. * @maxpop is the population limit. + * If @round_down, discard fractions instead of rounding them + * randomly. */ static int -babies(int adults, int etu, double brate, int food, int maxpop) +babies(int adults, int etu, double brate, int food, int maxpop, + int round_down) { - int new_birth, new_food, new; + double new_birth; + int new_food, new; if (adults >= maxpop) return 0; - new_birth = roundavg(brate * etu * adults); - if (opt_NOFOOD) - new_food = new_birth; - else - new_food = (int)(food / (2.0 * babyeat)); + new_birth = brate * etu * adults; + new = round_down ? (int)new_birth : roundavg(new_birth); + + if (!opt_NOFOOD) { + new_food = (int)(food / (2.0 * babyeat)); + if (new > new_food) + new = new_food; + } - new = new_birth; - if (new > new_food) - new = new_food; if (adults + new > maxpop) new = maxpop - adults; diff --git a/src/lib/update/sect.c b/src/lib/update/sect.c index 3394a652..152e9216 100644 --- a/src/lib/update/sect.c +++ b/src/lib/update/sect.c @@ -284,7 +284,7 @@ produce_sect(struct natstr *np, int etu, struct bp *bp, int p_sect[][2]) sp->sct_updated = 1; - work = do_feed(sp, np, etu); + work = do_feed(sp, np, etu, 0); bp_put_items(bp, sp); if (sp->sct_off || np->nat_money < 0) diff --git a/tests/update/journal.log b/tests/update/journal.log index 4d32fcfd..590746b7 100644 --- a/tests/update/journal.log +++ b/tests/update/journal.log @@ -62,12 +62,12 @@ Play#1 output Play#1 1 10,0 + 100% Play#1 output Play#1 1 12,0 + 100% Play#1 output Play#1 1 14,0 + 100% - Play#1 output Play#1 1 1,1 + 86% - Play#1 output Play#1 1 3,1 + 86% - Play#1 output Play#1 1 5,1 + 86% - Play#1 output Play#1 1 7,1 + 64% - Play#1 output Play#1 1 9,1 + 20% - Play#1 output Play#1 1 11,1 + 16% + Play#1 output Play#1 1 1,1 + 73% + Play#1 output Play#1 1 3,1 + 73% + Play#1 output Play#1 1 5,1 + 73% + Play#1 output Play#1 1 7,1 + 58% + Play#1 output Play#1 1 9,1 + 16% + Play#1 output Play#1 1 11,1 + 13% Play#1 output Play#1 1 13,1 a 100% Play#1 output Play#1 1 15,1 a 100% Play#1 output Play#1 1 2,2 g 88% @@ -132,7 +132,7 @@ Play#1 output Play#1 1 Thu Jan 1 00:00:00 1970 Play#1 output Play#1 1 PRODUCTION SIMULATION Play#1 output Play#1 1 sect des eff avail make p.e. cost use1 use2 use3 max1 max2 max3 max - Play#1 output Play#1 1 13,1 a 100% 26 214f 8.25 $0 214 + Play#1 output Play#1 1 13,1 a 100% 20 165f 8.25 $0 165 Play#1 output Play#1 1 15,1 a 100% 12 99f 8.25 $0 99 Play#1 output Play#1 1 2,2 g 0% 4 0d 1.00 $0 0 Play#1 output Play#1 1 9,3 e 100% 93 0m 1.00 $0 0c 0c 0