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 <armbru@pond.sub.org>
This commit is contained in:
Markus Armbruster 2016-06-04 09:50:09 +02:00
parent 43fc32a365
commit 41a2f7d1df
6 changed files with 40 additions and 56 deletions

View file

@ -663,8 +663,7 @@ extern int dodistribute(struct sctstr *, int, double);
/* finish.c */ /* finish.c */
extern void finish_sects(int); extern void finish_sects(int);
/* human.c */ /* human.c */
extern int new_work(struct sctstr *, int); extern int do_feed(struct sctstr *, struct natstr *, int, int);
extern int do_feed(struct sctstr *, struct natstr *, int);
extern int feed_people(short *, int); extern int feed_people(short *, int);
extern double food_needed(short *, int); extern double food_needed(short *, int);
extern int famine_victims(short *, int); extern int famine_victims(short *, int);

View file

@ -45,13 +45,10 @@ newe(void)
struct nstr_sect nstr; struct nstr_sect nstr;
double work, lcms, hcms; double work, lcms, hcms;
int nsect; int nsect;
int civs = 0;
int uws = 0;
int bwork; int bwork;
int twork; int twork;
int type; int type;
int eff; int eff;
int maxworkers;
if (!snxtsct(&nstr, player->argp[1])) if (!snxtsct(&nstr, player->argp[1]))
return RET_SYN; return RET_SYN;
@ -62,14 +59,8 @@ newe(void)
if (!player->owner) if (!player->owner)
continue; continue;
if (!sect.sct_off) { 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); natp = getnatp(sect.sct_own);
maxworkers = max_workers(natp->nat_level[NAT_RLEV], &sect); work = do_feed(&sect, natp, etu_per_update, 1);
work = new_work(&sect,
total_work(sect.sct_work, etu_per_update,
civs, sect.sct_item[I_MILIT], uws,
maxworkers));
bwork = work / 2; bwork = work / 2;
type = sect.sct_type; type = sect.sct_type;

View file

@ -89,13 +89,10 @@ prod(void)
char cmnem[MAXPRCON]; char cmnem[MAXPRCON];
int cuse[MAXPRCON], cmax[MAXPRCON]; int cuse[MAXPRCON], cmax[MAXPRCON];
int lcms, hcms; int lcms, hcms;
int civs;
int uws;
int bwork; int bwork;
int twork; int twork;
int type; int type;
int eff; int eff;
int maxworkers;
char mnem; char mnem;
if (!snxtsct(&nstr, player->argp[1])) if (!snxtsct(&nstr, player->argp[1]))
@ -106,20 +103,13 @@ prod(void)
while (nxtsct(&nstr, &sect)) { while (nxtsct(&nstr, &sect)) {
if (!player->owner) if (!player->owner)
continue; 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], &sect);
work = new_work(&sect,
total_work(sect.sct_work, etu_per_update,
civs, sect.sct_item[I_MILIT], uws,
maxworkers));
bwork = work / 2;
if (sect.sct_off) if (sect.sct_off)
continue; continue;
natp = getnatp(sect.sct_own);
work = do_feed(&sect, natp, etu_per_update, 1);
bwork = work / 2;
type = sect.sct_type; type = sect.sct_type;
eff = sect.sct_effic; eff = sect.sct_effic;
if (sect.sct_newtype != type) { if (sect.sct_newtype != type) {
@ -164,14 +154,13 @@ prod(void)
continue; continue;
if (type == SCT_ENLIST) { if (type == SCT_ENLIST) {
int maxpop = max_pop(natp->nat_level[NAT_RLEV], &sect);
int maxmil; int maxmil;
int enlisted; int enlisted;
if (sect.sct_own != sect.sct_oldown) if (sect.sct_own != sect.sct_oldown)
continue; continue;
enlisted = 0; 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) { if (maxmil > 0) {
enlisted = (etu_per_update enlisted = (etu_per_update
* (10 + sect.sct_item[I_MILIT]) * (10 + sect.sct_item[I_MILIT])

View file

@ -42,17 +42,19 @@
#include "update.h" #include "update.h"
#include "xy.h" #include "xy.h"
static int new_work(struct sctstr *, int);
static int growfood(struct sctstr *, int, int); static int growfood(struct sctstr *, int, int);
static int starve_some(short *, i_type, int); static int starve_some(short *, i_type, int);
static void trunc_people(struct sctstr *, struct natstr *); static void trunc_people(struct sctstr *, struct natstr *);
static int grow_people(struct sctstr *, int, struct natstr *); static int grow_people(struct sctstr *, int, struct natstr *, int);
static int babies(int, int, double, int, int); static int babies(int, int, double, int, int, int);
/* /*
* feed the individual sector * feed the individual sector
*/ */
int 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 work_avail;
int starved, sctwork; 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_MILIT],
sp->sct_item[I_UW], sp->sct_item[I_UW],
maxworkers)); maxworkers));
if (sp->sct_type != SCT_SANCT) { if (sp->sct_type != SCT_SANCT) {
manna = 0; manna = 0;
if (opt_NOFOOD == 0) { if (opt_NOFOOD == 0) {
@ -100,7 +101,7 @@ do_feed(struct sctstr *sp, struct natstr *np, int etu)
sctwork += 7 + roll(15); sctwork += 7 + roll(15);
if (sctwork > 100) if (sctwork > 100)
sctwork = 100; sctwork = 100;
grow_people(sp, etu, np); grow_people(sp, etu, np, round_babies_down);
work_avail = new_work(sp, work_avail = new_work(sp,
total_work(sp->sct_work, etu, total_work(sp->sct_work, etu,
sp->sct_item[I_CIVIL], sp->sct_item[I_CIVIL],
@ -124,7 +125,7 @@ do_feed(struct sctstr *sp, struct natstr *np, int etu)
return work_avail; return work_avail;
} }
int static int
new_work(struct sctstr *sp, int delta) new_work(struct sctstr *sp, int delta)
{ {
if (sp->sct_type == sp->sct_newtype) 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? * production? Maybe with just high education?
*/ */
static int 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 newciv;
int newuw; int newuw;
int maxpop = max_pop(np->nat_level[NAT_RLEV], sp); int maxpop = max_pop(np->nat_level[NAT_RLEV], sp);
newciv = babies(sp->sct_item[I_CIVIL], etu, obrate, 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; sp->sct_item[I_CIVIL] += newciv;
newuw = babies(sp->sct_item[I_UW], etu, uwbrate, 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; sp->sct_item[I_UW] += newuw;
/* /*
* subtract the baby eat food (if we are using FOOD) and return * 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. * @brate is the birth rate.
* @food is the food available for growing babies. * @food is the food available for growing babies.
* @maxpop is the population limit. * @maxpop is the population limit.
* If @round_down, discard fractions instead of rounding them
* randomly.
*/ */
static int 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) if (adults >= maxpop)
return 0; return 0;
new_birth = roundavg(brate * etu * adults); new_birth = brate * etu * adults;
if (opt_NOFOOD) new = round_down ? (int)new_birth : roundavg(new_birth);
new_food = new_birth;
else if (!opt_NOFOOD) {
new_food = (int)(food / (2.0 * babyeat)); 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) if (adults + new > maxpop)
new = maxpop - adults; new = maxpop - adults;

View file

@ -284,7 +284,7 @@ produce_sect(struct natstr *np, int etu, struct bp *bp, int p_sect[][2])
sp->sct_updated = 1; sp->sct_updated = 1;
work = do_feed(sp, np, etu); work = do_feed(sp, np, etu, 0);
bp_put_items(bp, sp); bp_put_items(bp, sp);
if (sp->sct_off || np->nat_money < 0) if (sp->sct_off || np->nat_money < 0)

View file

@ -62,12 +62,12 @@
Play#1 output Play#1 1 10,0 + 100% Play#1 output Play#1 1 10,0 + 100%
Play#1 output Play#1 1 12,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 14,0 + 100%
Play#1 output Play#1 1 1,1 + 86% Play#1 output Play#1 1 1,1 + 73%
Play#1 output Play#1 1 3,1 + 86% Play#1 output Play#1 1 3,1 + 73%
Play#1 output Play#1 1 5,1 + 86% Play#1 output Play#1 1 5,1 + 73%
Play#1 output Play#1 1 7,1 + 64% Play#1 output Play#1 1 7,1 + 58%
Play#1 output Play#1 1 9,1 + 20% Play#1 output Play#1 1 9,1 + 16%
Play#1 output Play#1 1 11,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 13,1 a 100%
Play#1 output Play#1 1 15,1 a 100% Play#1 output Play#1 1 15,1 a 100%
Play#1 output Play#1 1 2,2 g 88% 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 Thu Jan 1 00:00:00 1970
Play#1 output Play#1 1 PRODUCTION SIMULATION 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 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 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 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 Play#1 output Play#1 1 9,3 e 100% 93 0m 1.00 $0 0c 0c 0