]> git.pond.sub.org Git - empserver/blobdiff - src/lib/commands/buil.c
build: Fix inexact calculation of required materials
[empserver] / src / lib / commands / buil.c
index 3fafc904293deac3e8439f82e812d6513de729d1..700113047aa9b8c8382247518f7729900fc4cf68 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2014, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                Ken Stevens, Steve McClure, Markus Armbruster
  *
  *  Empire is free software: you can redistribute it and/or modify
@@ -28,7 +28,7 @@
  *
  *  Known contributors to this file:
  *     Steve McClure, 1998-2000
- *     Markus Armbruster, 2004-2014
+ *     Markus Armbruster, 2004-2015
  */
 
 #include <config.h>
@@ -151,6 +151,8 @@ buil(void)
        return RET_FAIL;
     }
 
+    if (tlev < rqtech && player->god)
+       tlev = rqtech;
     if (type < 0 || tlev < rqtech) {
        pr("You can't build that!\n");
        pr("Use `show %s build %d' to show types you can build.\n",
@@ -217,7 +219,7 @@ build_ship(struct sctstr *sp, int type, int tlev)
     mat[I_HCM] = mp->m_hcm;
     work = SHP_BLD_WORK(mp->m_lcm, mp->m_hcm);
 
-    if (sp->sct_type != SCT_HARBR) {
+    if (sp->sct_type != SCT_HARBR && !player->god) {
        pr("Ships must be built in harbours.\n");
        return 0;
     }
@@ -270,7 +272,7 @@ build_land(struct sctstr *sp, int type, int tlev)
     mat[I_HCM] = lp->l_hcm;
     work = LND_BLD_WORK(lp->l_lcm, lp->l_hcm);
 
-    if (sp->sct_type != SCT_HEADQ) {
+    if (sp->sct_type != SCT_HEADQ && !player->god) {
        pr("Land units must be built in headquarters.\n");
        return 0;
     }
@@ -431,7 +433,7 @@ build_bridge(char what)
 
     switch (what) {
     case 'b':
-       if (natp->nat_level[NAT_TLEV] < buil_bt) {
+       if (natp->nat_level[NAT_TLEV] < buil_bt && !player->god) {
            pr("Building a span requires a tech of %.0f\n", buil_bt);
            return RET_FAIL;
        }
@@ -442,7 +444,7 @@ build_bridge(char what)
            pr("Bridge tower building is disabled.\n");
            return RET_FAIL;
        }
-       if (natp->nat_level[NAT_TLEV] < buil_tower_bt) {
+       if (natp->nat_level[NAT_TLEV] < buil_tower_bt && !player->god) {
            pr("Building a tower requires a tech of %.0f\n",
               buil_tower_bt);
            return RET_FAIL;
@@ -477,11 +479,11 @@ build_bspan(struct sctstr *sp)
     int work;
     int val;
     int newx, newy;
-    int nx, ny, i, good = 0;
     char *p;
     char buf[1024];
 
-    if (opt_EASY_BRIDGES == 0) {       /* must have a bridge head or tower */
+    if (!opt_EASY_BRIDGES && !player->god) {
+       /* must have a bridge head or tower */
        if (sp->sct_type != SCT_BTOWER) {
            if (sp->sct_type != SCT_BHEAD)
                return 0;
@@ -521,23 +523,20 @@ build_bspan(struct sctstr *sp)
        pr("%s is not a water sector\n", xyas(newx, newy, player->cnum));
        return 0;
     }
-    if (opt_EASY_BRIDGES) {
-       good = 0;
-
-       for (i = 1; i <= 6; i++) {
-           struct sctstr s2;
-           nx = sect.sct_x + diroff[i][0];
-           ny = sect.sct_y + diroff[i][1];
-           getsect(nx, ny, &s2);
-           if ((s2.sct_type != SCT_WATER) && (s2.sct_type != SCT_BSPAN))
-               good = 1;
-       }
-       if (!good) {
-           pr("Bridges must be built adjacent to land or bridge towers.\n");
-           pr("That sector is not adjacent to land or a bridge tower.\n");
-           return 0;
+    if (!bridge_support_at(&sect, DIR_STOP)) {
+       if (opt_EASY_BRIDGES) {
+           pr("%s is not next to land or a bridge tower",
+              xyas(newx, newy, player->cnum));
+       } else {
+           /*
+            * Note: because players need a 60% bridge head or tower,
+            * we can get here only for a deity.
+            */
+           pr("%s is not next to a supporting bridge head or tower\n",
+              xyas(newx, newy, player->cnum));
        }
-    }                          /* end EASY_BRIDGES */
+       return 0;
+    }
     build_charge(sp, mat, work, buil_bc, 100);
 
     sect.sct_type = SCT_BSPAN;
@@ -575,7 +574,7 @@ build_btower(struct sctstr *sp)
     int nx;
     int ny;
 
-    if (sp->sct_type != SCT_BSPAN) {
+    if (sp->sct_type != SCT_BSPAN && !player->god) {
        pr("Bridge towers can only be built from bridge spans.\n");
        return 0;
     }
@@ -620,8 +619,8 @@ build_btower(struct sctstr *sp)
        getsect(nx, ny, &s2);
        if ((s2.sct_type != SCT_WATER) &&
            (s2.sct_type != SCT_BTOWER) && (s2.sct_type != SCT_BSPAN)) {
-           pr("Bridge towers cannot be built adjacent to land.\n");
-           pr("That sector is adjacent to land.\n");
+           pr("%s is next to land, can't build bridge tower there",
+              xyas(newx, newy, player->cnum));
            return 0;
        }
     }
@@ -653,8 +652,11 @@ 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 */
 
     if (sp->sct_effic < 60 && !player->god) {
        pr("Sector %s is not 60%% efficient.\n",
@@ -672,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;
@@ -691,6 +694,9 @@ build_charge(struct sctstr *sp,
 {
     int i;
 
+    if (player->god)
+       return;                 /* Deity builds ex nihilo */
+
     for (i = I_NONE + 1; i <= I_MAX; i++)
        sp->sct_item[i] -= mat[i];
     sp->sct_avail -= (work * effic + 99) / 100;