]> git.pond.sub.org Git - empserver/blobdiff - src/lib/subs/supply.c
Don't let automatic supply starve the sector containing the sink
[empserver] / src / lib / subs / supply.c
index 521b0f9654f1f07f098c7a8a101a7d7af14945c0..dbe725720dc79da39c686a451141b3fa26b69eb5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -26,9 +26,9 @@
  *  ---
  *
  *  supply.c: Supply subroutines
- * 
+ *
  *  Known contributors to this file:
- *  
+ *
  */
 
 #include <config.h>
@@ -48,15 +48,14 @@ static int s_commod(int, int, int, i_type, int, int);
 
 /*
  * We want to get enough guns to be maxed out, enough shells to
- *     fire once, one update's worth of food, enough fuel for
- *     one update.
+ *     fire once, one update's worth of food.
  *
  * Firts, try to forage in the sector
  * Second look for a warehouse or headquarters to leech
  * Third, look for a ship we own in a harbor
  * Fourth, look for supplies in a supply unit we own
- *             (one good reason to do this last is that the supply
- *              unit will then call resupply, taking more time)
+ *             (one good reason to do this last is that the supply
+ *              unit will then call resupply, taking more time)
  *
  * May want to put code to resupply with SAMs here, later --ts
  */
@@ -67,8 +66,6 @@ resupply_all(struct lndstr *lp)
     if (!opt_NOFOOD)
        resupply_commod(lp, I_FOOD);
     resupply_commod(lp, I_SHELL);
-    if (opt_FUEL)
-       resupply_commod(lp, I_PETROL);
 }
 
 /*
@@ -80,42 +77,23 @@ void
 resupply_commod(struct lndstr *lp, i_type type)
 {
     int amt;
-    struct shpstr ship;
 
-    /* Ok, do we now have enough? */
     amt = get_minimum(lp, type) - lp->lnd_item[type];
     if (amt > 0) {
        lp->lnd_item[type] += supply_commod(lp->lnd_own,
                                            lp->lnd_x, lp->lnd_y,
                                            type, amt);
-       amt = get_minimum(lp, type) - lp->lnd_item[type];
     }
-    /* Now, check again to see if we have enough. */
-    if (amt > 0) {
-       /* Are we on a ship?  if so, try to get it from the ship first. */
-       if (lp->lnd_ship >= 0) {
-           getship(lp->lnd_ship, &ship);
-           /* Now, determine how much we can get */
-           if (amt > ship.shp_item[type])
-               amt = ship.shp_item[type];
-           /* Now, add and subtract */
-           lp->lnd_item[type] += amt;
-           ship.shp_item[type] -= amt;
-           putship(lp->lnd_ship, &ship);
-       }
-    }
-
-    if (opt_FUEL && type == I_PETROL) {
-       int fuel_needed = lchr[lp->lnd_type].l_fuelu
-           * ((float)etu_per_update * land_mob_scale) / 10.0;
+}
 
-       while ((lp->lnd_fuel < fuel_needed) && lp->lnd_item[I_PETROL]) {
-           lp->lnd_fuel += 10;
-           if (lp->lnd_fuel > lchr[lp->lnd_type].l_fuelc)
-               lp->lnd_fuel = lchr[lp->lnd_type].l_fuelc;
-           lp->lnd_item[I_PETROL]--;
-       }
+int
+lnd_in_supply(struct lndstr *lp)
+{
+    if (!opt_NOFOOD) {
+       if (lp->lnd_item[I_FOOD] < get_minimum(lp, I_FOOD))
+           return 0;
     }
+    return lp->lnd_item[I_SHELL] >= get_minimum(lp, I_SHELL);
 }
 
 /*
@@ -124,7 +102,7 @@ resupply_commod(struct lndstr *lp, i_type type)
 int
 supply_commod(int own, int x, int y, i_type type, int total_wanted)
 {
-    if (total_wanted < 0)
+    if (total_wanted <= 0)
        return 0;
     return s_commod(own, x, y, type, total_wanted, !player->simulation);
 }
@@ -132,10 +110,10 @@ supply_commod(int own, int x, int y, i_type type, int total_wanted)
 /*
  * Just return the number you COULD get, without doing it
  */
-int
+static int
 try_supply_commod(int own, int x, int y, i_type type, int total_wanted)
 {
-    if (total_wanted < 0)
+    if (total_wanted <= 0)
        return 0;
 
     return s_commod(own, x, y, type, total_wanted, 0);
@@ -155,7 +133,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
     struct shpstr ship;
     struct lndstr land;
     /* leave at least 1 military in sectors/ships */
-    int minimum = (type == I_MILIT ? 1 : 0);
+    int minimum = 0;
     int can_move;
     double move_cost, weight, mobcost;
     int packing;
@@ -167,6 +145,9 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
     getsect(x, y, &dest);
     getsect(x, y, &sect);
     if (sect.sct_own == own) {
+       if (!opt_NOFOOD && type == I_FOOD)
+           minimum = 1 + (int)ceil(food_needed(sect.sct_item,
+                                               etu_per_update));
        if (sect.sct_item[type] - wanted >= minimum) {
            sect.sct_item[type] -= wanted;
            if (actually_doit)
@@ -224,7 +205,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
            sect.sct_item[type] -= wanted;
 
            /* take off mobility for delivering sect */
-           n = roundavg(total_wanted * weight * move_cost);
+           n = roundavg(wanted * weight * move_cost);
            if (n < 0)
                n = 0;
            if (n > sect.sct_mobil)
@@ -351,6 +332,23 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
        if ((land.lnd_ship >= 0) && (sect.sct_effic < 2))
            continue;
 
+#if 0
+       /*
+        * Recursive supply is disabled for now.  It can introduce
+        * cycles into the "resupplies from" relation.  The code below
+        * attempts to break these cycles by temporarily zapping the
+        * commodity being supplied.  That puts the land file in a
+        * funny state temporarily, risking loss of supplies when
+        * something goes wrong on the way.  Worse, it increases
+        * lnd_seqno even when !actually_doit, which can lead to
+        * spurious seqno mismatch oopses in users of
+        * lnd_could_be_supplied().  I can't be bothered to clean up
+        * this mess right now, because recursive resupply is too dumb
+        * to be really useful anyway: each step uses the first source
+        * it finds, without consideration of mobility cost.  If you
+        * re-enable it, don't forget to uncomment its documentation
+        * in supply.t as well.
+        */
        if (land.lnd_item[type] - wanted < get_minimum(&land, type)) {
            struct lndstr save;
 
@@ -361,6 +359,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
            save = land;
            land.lnd_item[type] = 0;
            putland(land.lnd_uid, &land);
+           save.lnd_seqno = land.lnd_seqno;
 
            land.lnd_item[type] =
                save.lnd_item[type] + s_commod(own, land.lnd_x, land.lnd_y,
@@ -370,6 +369,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
            else
                putland(save.lnd_uid, &save);
        }
+#endif
 
        min = get_minimum(&land, type);
        ip = &ichr[type];
@@ -384,10 +384,6 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
 
        if (can_move >= wanted) {
            land.lnd_item[type] -= wanted;
-
-           /* resupply the supply unit */
-           resupply_commod(&land, type);
-
            land.lnd_mobil -= roundavg(wanted * weight * move_cost);
 
            if (actually_doit)
@@ -413,8 +409,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
 
 /*
  * We want to get enough shells to fire once,
- * one update's worth of food, enough fuel for
- * one update.
+ * one update's worth of food.
  */
 
 static int
@@ -435,25 +430,6 @@ get_minimum(struct lndstr *lp, i_type type)
     case I_SHELL:
        want = lcp->l_ammo;
        break;
-
-       /*
-        * return the amount of pet we'd need to get to 
-        * enough fuel for 1 update
-        */
-    case I_PETROL:
-       if (opt_FUEL == 0)
-           return 0;
-       want = lcp->l_fuelu * ((float)etu_per_update * land_mob_scale)
-           / 10.0;
-       want -= lp->lnd_fuel;
-       if (want > 0) {
-           want = want / 10;
-           if (want == 0)
-               want++;
-       }
-
-       max = want;
-       break;
     default:
        return 0;
     }
@@ -465,11 +441,10 @@ get_minimum(struct lndstr *lp, i_type type)
 }
 
 int
-has_supply(struct lndstr *lp)
+lnd_could_be_supplied(struct lndstr *lp)
 {
     int shells_needed, shells, keepshells;
     int food, food_needed, keepfood;
-    int fuel_needed, fuel, petrol_needed, petrol, keeppetrol;
 
     if (!opt_NOFOOD) {
        food_needed = get_minimum(lp, I_FOOD);
@@ -501,29 +476,5 @@ has_supply(struct lndstr *lp)
     if (shells < shells_needed)
        return 0;
 
-    if (opt_FUEL) {
-       fuel_needed = lchr[lp->lnd_type].l_fuelu;
-       fuel = lp->lnd_fuel;
-       if (fuel < fuel_needed) {
-           petrol_needed =
-               ldround((fuel_needed - fuel) / 10.0, 1);
-           petrol = keeppetrol = lp->lnd_item[I_PETROL];
-           if (petrol < petrol_needed) {
-               lp->lnd_item[I_PETROL] = 0;
-               putland(lp->lnd_uid, lp);
-               petrol += try_supply_commod(lp->lnd_own,
-                                           lp->lnd_x, lp->lnd_y,
-                                           I_PETROL,
-                                           (petrol_needed - petrol));
-               lp->lnd_item[I_PETROL] = keeppetrol;
-               putland(lp->lnd_uid, lp);
-           }
-           fuel += petrol * 10;
-       }
-
-       if (fuel < fuel_needed)
-           return 0;
-    }
-    /* end opt_FUEL */
     return 1;
 }