]> git.pond.sub.org Git - empserver/commitdiff
neweff production: Consider insufficient food
authorMarkus Armbruster <armbru@pond.sub.org>
Sat, 4 Jun 2016 07:50:09 +0000 (09:50 +0200)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 6 Aug 2017 17:59:57 +0000 (19:59 +0200)
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>
include/prototypes.h
src/lib/commands/newe.c
src/lib/commands/prod.c
src/lib/update/human.c
src/lib/update/sect.c
tests/update/journal.log

index 564ace374d65d324924a5469203f430d79cae2c1..2d6576c6eb6ee3b89f85fde473eaf54c42fbf097 100644 (file)
@@ -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);
index 04cc24a6b8c7305bc6a62129f769c82de26e31a7..5351c78e477ca760e24dba9c94b9ec6b0d609c3f 100644 (file)
@@ -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], &sect);
-           work = new_work(&sect,
-                           total_work(sect.sct_work, etu_per_update,
-                                      civs, sect.sct_item[I_MILIT], uws,
-                                      maxworkers));
+           work = do_feed(&sect, natp, etu_per_update, 1);
            bwork = work / 2;
 
            type = sect.sct_type;
index 2f5527100d3f451f309133d4706b3d3bfd882587..60ed59aa06d59aa2e8b0572eb67f832f54481fc0 100644 (file)
@@ -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, &sect)) {
        if (!player->owner)
            continue;
+       if (sect.sct_off)
+           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));
+       work = do_feed(&sect, natp, etu_per_update, 1);
        bwork = work / 2;
 
-       if (sect.sct_off)
-           continue;
        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], &sect);
            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])
index e05aa6b8d304beb71d6df08c9dbda820e91f270d..f8eef410e2faffb966ef2ea668dec99405461153 100644 (file)
 #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_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;
 
index 3394a652a59ad92a5e25f788bb1603324b49a932..152e9216b7d02468108125986bd51fde284c5d5e 100644 (file)
@@ -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)
index 4d32fcfd16809b92849f5ca405f667893b01b0bd..590746b7c6df3808d531a7ce06fe7380db65f8e5 100644 (file)
     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%
     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