build: Fix inexact calculation of required materials
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 8 Mar 2015 13:06:02 +0000 (14:06 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 8 Mar 2015 13:06:02 +0000 (14:06 +0100)
sector_can_build() computes mat[i] * (effic / 100.0).  The division is
inexact.  The result gets randomly rounded, so errors are vanishingly
unlikely to screw up material consumption.

However, we require the amount rounded up to be present since commit
1227d2c.  Errors *can* screw that up.  Fix by avoiding inexact
computation for that part.

We should probably review rounding of inexact values in general.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
src/lib/commands/buil.c

index b30049bb73221033fea775da53f12cab0e780bbd..700113047aa9b8c8382247518f7729900fc4cf68 100644 (file)
@@ -28,7 +28,7 @@
  *
  *  Known contributors to this file:
  *     Steve McClure, 1998-2000
- *     Markus Armbruster, 2004-2014
+ *     Markus Armbruster, 2004-2015
  */
 
 #include <config.h>
@@ -652,8 +652,8 @@ static int
 sector_can_build(struct sctstr *sp, short mat[], int work,
                 int effic, char *what)
 {
-    int i, avail, ret;
-    double needed;
+    int i, avail, ret, req;
+    double used;
 
     if (player->god)
        return 1;               /* Deity builds ex nihilo */
@@ -674,14 +674,15 @@ sector_can_build(struct sctstr *sp, short mat[], int work,
 
     ret = 1;
     for (i = I_NONE + 1; i <= I_MAX; i++) {
-       needed = mat[i] * (effic / 100.0);
-       if (sp->sct_item[i] < needed) {
-           pr("Not enough %s in %s (need %g more)\n",
+       used = mat[i] * effic;
+       req = (used + 99) / 100;
+       if (sp->sct_item[i] < req) {
+           pr("Not enough %s in %s (need %d more)\n",
               ichr[i].i_name, xyas(sp->sct_x, sp->sct_y, player->cnum),
-              ceil(needed - sp->sct_item[i]));
+              req - sp->sct_item[i]);
            ret = 0;
        }
-       mat[i] = roundavg(needed);
+       mat[i] = roundavg(used / 100.0);
     }
 
     return ret;