]> git.pond.sub.org Git - empserver/blobdiff - src/lib/update/mobility.c
Update copyright notice
[empserver] / src / lib / update / mobility.c
index 36983252350a8336a892f8b87d30cdaad4863435..73330f6cef9da5855468b19079b3ea495694206f 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
- *                           Ken Stevens, Steve McClure
+ *  Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *                Ken Stevens, Steve McClure, Markus Armbruster
  *
- *  This program is free software; you can redistribute it and/or modify
+ *  Empire is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
+ *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  ---
  *
- *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- *  related information and legal notices. It is expected that any future
- *  projects/authors will amend these files as needed.
+ *  See files README, COPYING and CREDITS in the root of the source
+ *  tree for related information and legal notices.  It is expected
+ *  that future projects/authors will amend these files as needed.
  *
  *  ---
  *
  *  mobility.c: Add mobility to each of the items which accumulate mobility.
- * 
+ *
  *  Known contributors to this file:
  *     Dave Pare, 1986
  *     Steve McClure, 1998-1999
+ *     Markus Armbruster, 2004-2008
  */
 
-#include "misc.h"
-#include "var.h"
-#include "sect.h"
-#include "ship.h"
+#include <config.h>
+
+#include "game.h"
 #include "land.h"
 #include "plane.h"
-#include "nat.h"
-#include "file.h"
-#include "optlist.h"
-#include "mission.h"
+#include "server.h"
+#include "ship.h"
 #include "update.h"
-#include "gen.h"
-#include "subs.h"
-#include "optlist.h"
-
-extern int timestamp_fixing;
-extern int update_pending;
-int do_upd_checking = 0;
-
-
-int
-increase_mob(time_t *counter, float mult)
-{
-    time_t secs;
-    time_t now;
-    time_t left;
-    extern long s_p_etu;
-    extern int updating_mob;
-    int newetus;
-    float newmob;
-    int   inewmob;
-
-    time(&now);
 
-    secs = now - *counter;
-    if (secs < 1 || secs < s_p_etu)
-        return 0;
-    newetus = (int)(secs / s_p_etu); 
-    if (newetus < 1)
-       return 0;
-    left = (secs % s_p_etu);
-    do {
-      newmob = (float)(newetus * mult);
-      inewmob = (int)(newetus * mult);
-      if (newmob == inewmob || newetus > 7)
-        break;
-      newetus--;
-      left += s_p_etu;
-    } while (newetus > 0);
-    if (newetus <= 0)
-      return 0;
-
-    time(counter);
-    *counter = *counter - left;
-
-    if (updating_mob)
-      return (newetus);
-    return 0;
-}
+static int do_upd_checking;
 
-void
-update_timestamps(time_t lastsavedtime)
-{
-  struct shpstr *shipp;
-  struct sctstr *sectp;
-  struct lndstr *landp;
-  struct plnstr *planep;
-  int n;
-  time_t now;
-  time_t delta;
-
-  timestamp_fixing = 1;
-  time(&now);
-  delta = now - lastsavedtime; 
-  for (n = 0; (shipp = getshipp(n)); n++)
-    shipp->shp_access += delta;
-  for (n = 0; (sectp = getsectid(n)); n++)
-    sectp->sct_access += delta;
-  for (n = 0; (landp = getlandp(n)); n++)
-    landp->lnd_access += delta;
-  for (n = 0; (planep = getplanep(n)); n++)
-    planep->pln_access += delta;
-  timestamp_fixing = 0;
-}
+static void do_mob_land(struct lndstr *, int);
+static void do_mob_plane(struct plnstr *, int);
+static void do_mob_sect(struct sctstr *sp, int etus);
+static void do_mob_ship(struct shpstr *, int);
 
 void
-update_all_mob(void)
+sct_do_upd_mob(struct sctstr *sp)
 {
-  struct shpstr *shipp;
-  struct sctstr *sectp;
-  struct lndstr *landp;
-  struct plnstr *planep;
-  int n;
-
-  n = 0;
-  while (1) {
-    do_upd_checking = 1;
-    shipp = getshipp(n);
-    sectp = getsectid(n);
-    landp = getlandp(n);
-    planep = getplanep(n);
-    do_upd_checking = 0;
-    if (shipp)
-      shp_do_upd_mob(shipp);
-    if (sectp)
-      sct_do_upd_mob(sectp);
-    if (landp)
-      lnd_do_upd_mob(landp);
-    if (planep)
-      pln_do_upd_mob(planep);
-    if (!shipp && !sectp && !landp && !planep)
-      break;
-    n++;
-  }
-  do_upd_checking = 0;
-}
-
-void
-sct_do_upd_mob(register struct sctstr *sp)
-{
-    extern float sect_mob_scale;
     int etus;
 
-    if (do_upd_checking || timestamp_fixing || update_pending)
-        return;
+    if (do_upd_checking || update_running)
+       return;
     if (sp->sct_own == 0)
-        return;
+       return;
     if (sp->sct_type == SCT_SANCT)
-        return;
-    if ((etus = increase_mob(&sp->sct_access, sect_mob_scale)) == 0)
        return;
-    do_upd_checking = 1;
+    etus = game_tick_to_now(&sp->sct_access);
+    if (etus == 0)
+       return;
+
+    do_upd_checking = 1;       /* avoid recursion */
     do_mob_sect(sp, etus);
-/*    putsect(sp);*/
     do_upd_checking = 0;
 }
 
 void
-shp_do_upd_mob(register struct shpstr *sp)
+shp_do_upd_mob(struct shpstr *sp)
 {
-    extern float ship_mob_scale;
     int etus;
 
-    if (do_upd_checking || timestamp_fixing || update_pending)
-        return;
+    if (do_upd_checking || update_running)
+       return;
     if (sp->shp_own == 0)
-        return;
-    if ((etus = increase_mob(&sp->shp_access, ship_mob_scale)) == 0)
-        return;
-    do_upd_checking = 1;
+       return;
+    etus = game_tick_to_now(&sp->shp_access);
+    if (etus == 0)
+       return;
+
+    do_upd_checking = 1;       /* avoid recursion */
     do_mob_ship(sp, etus);
     do_upd_checking = 0;
 }
 
 void
-lnd_do_upd_mob(register struct lndstr *lp)
+lnd_do_upd_mob(struct lndstr *lp)
 {
-    extern float land_mob_scale;
     int etus;
 
-    if (do_upd_checking || timestamp_fixing || update_pending)
-        return;
+    if (do_upd_checking || update_running)
+       return;
     if (lp->lnd_own == 0)
-        return;
-    if ((etus = increase_mob(&lp->lnd_access, land_mob_scale)) == 0)
-        return;
+       return;
+    etus = game_tick_to_now(&lp->lnd_access);
+    if (etus == 0)
+       return;
 
-    do_upd_checking = 1;
+    do_upd_checking = 1;       /* avoid recursion */
     do_mob_land(lp, etus);
     do_upd_checking = 0;
 }
 
 void
-pln_do_upd_mob(register struct plnstr *pp)
+pln_do_upd_mob(struct plnstr *pp)
 {
-    extern float plane_mob_scale;
     int etus;
 
-    if (do_upd_checking || timestamp_fixing || update_pending)
-        return;
+    if (do_upd_checking || update_running)
+       return;
     if (pp->pln_own == 0)
-        return;
-    if ((etus = increase_mob(&pp->pln_access, plane_mob_scale)) == 0)
-        return;
+       return;
+    etus = game_tick_to_now(&pp->pln_access);
+    if (etus == 0)
+       return;
 
-    do_upd_checking = 1;
+    do_upd_checking = 1;       /* avoid recursion */
     do_mob_plane(pp, etus);
     do_upd_checking = 0;
 }
 
 void
-mob_sect(register int etus)
+mob_sect(void)
 {
-        register struct sctstr *sp;
-        register int n;
-       time_t now;
-
-       time(&now);
-        for (n=0; NULL != (sp = getsectid(n)); n++) {
-           sp->sct_timestamp = now;
-           if (opt_MOB_ACCESS)
-             sct_do_upd_mob(sp);
-           else
-             do_mob_sect(sp, etus);
-        }
+    struct sctstr *sp;
+    int n, etus;
+    time_t now;
+
+    time(&now);
+    for (n = 0; NULL != (sp = getsectid(n)); n++) {
+       sp->sct_timestamp = now;
+       if (opt_MOB_ACCESS)
+           etus = game_reset_tick(&sp->sct_access);
+       else
+           etus = etu_per_update;
+       do_mob_sect(sp, etus);
+    }
 }
 
-void
-do_mob_sect(register struct sctstr *sp, register int etus)
+static void
+do_mob_sect(struct sctstr *sp, int etus)
 {
-       extern  float sect_mob_scale;
-       extern  int sect_mob_max;
-       register int value;
+    int value;
+
+    if (CANT_HAPPEN(etus < 0))
+       etus = 0;
 
     if (sp->sct_own == 0)
-        return;
+       return;
     if (sp->sct_type == SCT_SANCT)
-        return;
-       /* Do we have to even bother? */
-       if (sp->sct_mobil >= sect_mob_max) {
-               /* No, so set just in case and then return */
-               sp->sct_mobil = sect_mob_max;
-               return;
-       }
-       value = sp->sct_mobil + ((float)etus * sect_mob_scale);
-       if (value > sect_mob_max)
-               value = sect_mob_max;
-       sp->sct_mobil = value;
+       return;
+
+    value = sp->sct_mobil + ((float)etus * sect_mob_scale);
+    if (value > sect_mob_max)
+       value = sect_mob_max;
+    sp->sct_mobil = value;
 }
 
 void
-mob_ship(register int etus)
+mob_ship(void)
 {
-       register struct shpstr *sp;
-       register int n;
-       time_t now;
-       
-       time(&now);
-       for (n=0; NULL != (sp = getshipp(n)); n++) {
-           sp->shp_timestamp = now;
-           if (opt_MOB_ACCESS)
-                       shp_do_upd_mob(sp);
-           else
-                       do_mob_ship(sp, etus);
-       }
+    struct shpstr *sp;
+    int n, etus;
+    time_t now;
+
+    time(&now);
+    for (n = 0; NULL != (sp = getshipp(n)); n++) {
+       sp->shp_timestamp = now;
+       if (opt_MOB_ACCESS)
+           etus = game_reset_tick(&sp->shp_access);
+       else
+           etus = etu_per_update;
+       do_mob_ship(sp, etus);
+    }
 }
 
-void
-do_mob_ship(register struct shpstr *sp, register int etus)
+static void
+do_mob_ship(struct shpstr *sp, int etus)
 {
-    extern  int ship_mob_max;
-    extern  float ship_mob_scale;
-    int     newfuel=0;
-    register int value;
-    int     can_add,have_fuel_for,total_add;
-    double  d;
-    extern  int fuel_mult;
+    int value;
 
-    if (sp->shp_own == 0)
-        return;
-
-       /* Do we even have to bother updating this mobility? */
-       if (sp->shp_mobil >= ship_mob_max) {
-               /* No, so don't.  Just set it to max (just in case) and
-                  return. */
-               sp->shp_mobil = ship_mob_max;
-               return;
-       }
+    if (CANT_HAPPEN(etus < 0))
+       etus = 0;
 
-    if (opt_FUEL == 0) { /* only a bit to do ... */
-        value = sp->shp_mobil + ((float)etus * ship_mob_scale);
-        if (value > ship_mob_max)
-            value = ship_mob_max;
-        sp->shp_mobil = value;
-        return; /* so we ship the FUEL stuff */
-    }
+    if (sp->shp_own == 0)
+       return;
 
-    /* opt_FUEL in force */
-    if (mchr[(int)sp->shp_type].m_fuelu == 0) {
-        value = sp->shp_mobil + ((float)etus * ship_mob_scale);
-        if (value > ship_mob_max)
-            value = ship_mob_max;
-        sp->shp_mobil = (s_char)value;
-    } else {
-        can_add = ship_mob_max - sp->shp_mobil;
-        if (can_add > ((float)etus*ship_mob_scale))
-            can_add = ((float)etus*ship_mob_scale);
-        have_fuel_for = ldround((((double)sp->shp_fuel /
-                                  (double)mchr[(int)sp->shp_type].m_fuelu)*
-                                 (double)fuel_mult),1);
-
-        if (can_add > have_fuel_for){
-            int     need;
-            need = can_add - have_fuel_for;
-            d = (double)need;
-            d *= (double)mchr[(int)sp->shp_type].m_fuelu;
-            d /= (double)fuel_mult;
-            d /= 5.0;
-            if ((d-(int)d) > 0.0)
-                d++;
-            need = (int)d;
-            newfuel = supply_commod(sp->shp_own,sp->shp_x,
-                                    sp->shp_y,I_PETROL,need);
-            sp->shp_fuel += (u_char)(newfuel * 5);
-        }
-
-        have_fuel_for = ldround((((double)sp->shp_fuel /
-                                  (double)mchr[(int)sp->shp_type].m_fuelu)*
-                                 (double)fuel_mult),1);
-
-        if (can_add > have_fuel_for){
-            int     need;
-            need = can_add - have_fuel_for;
-            d = (double)need;
-            d *= (double)mchr[(int)sp->shp_type].m_fuelu;
-            d /= (double)fuel_mult;
-            d /= 50.0;
-            if ((d-(int)d) > 0.0)
-                d++;
-            need = (int)d;
-            newfuel = supply_commod(sp->shp_own,sp->shp_x,
-                                    sp->shp_y,I_OIL,need);
-            sp->shp_fuel += (u_char)(newfuel * 50);
-        }
-
-        have_fuel_for = ldround((((double)sp->shp_fuel /
-                                  (double)mchr[(int)sp->shp_type].m_fuelu)*
-                                 (double)fuel_mult),1);
-
-        if (can_add > have_fuel_for)
-            total_add = have_fuel_for;
-        else
-            total_add = can_add;
-        d = (double)total_add;
-        d *= (double)mchr[(int)sp->shp_type].m_fuelu;
-        d /= (double)fuel_mult;
-        sp->shp_fuel -= (u_char)ldround(d,1);
-        sp->shp_fuel = (u_char)min(sp->shp_fuel,
-                           mchr[(int)sp->shp_type].m_fuelc);
-        sp->shp_mobil += (s_char)total_add;
-    }
+    value = sp->shp_mobil + (float)etus * ship_mob_scale;
+    if (value > ship_mob_max)
+       value = ship_mob_max;
+    sp->shp_mobil = (signed char)value;
 }
 
 void
-mob_land(register int etus)
+mob_land(void)
 {
-        register struct lndstr *lp;
-        register int n;
-       time_t now;
-
-       time(&now);
-        for (n=0; NULL != (lp = getlandp(n)); n++) {
-           lp->lnd_timestamp = now;
-           if (opt_MOB_ACCESS)
-             lnd_do_upd_mob(lp);
-           else
-             do_mob_land(lp, etus);
-        }
+    struct lndstr *lp;
+    int n, etus;
+    time_t now;
+
+    time(&now);
+    for (n = 0; NULL != (lp = getlandp(n)); n++) {
+       lp->lnd_timestamp = now;
+       if (opt_MOB_ACCESS)
+           etus = game_reset_tick(&lp->lnd_access);
+       else
+           etus = etu_per_update;
+       do_mob_land(lp, etus);
+    }
 }
 
-void
-do_mob_land(register struct lndstr *lp, register int etus)
+static void
+do_mob_land(struct lndstr *lp, int etus)
 {
-    extern  int land_mob_max;
-    extern  float land_mob_scale;
-    int     newfuel=0;
-    register int value;
-    int     can_add,have_fuel_for,total_add;
-    double  d;
-    extern  int fuel_mult;
-    
-    if (lp->lnd_own == 0)
-        return;
-    
-       if (lp->lnd_mobil >= land_mob_max) {
-               lp->lnd_mobil = land_mob_max;
-               return;
-       }
+    int value;
 
-    /*
-     * Give damaged units a break. When at low
-     * efficiency, units can go to -100 mob when
-     * marching 1 step, making them slower than
-     * normal mil. This helps take the curse off.
-     * If MOB_ACCESS is on, we don't do this, as it would
-     * be too much of an advantage.  So, we just add double
-     * the small amount of mob if we are < 0 instead.
-     */
-    
-    if (!opt_MOB_ACCESS) {
-      if (lp->lnd_mobil < 0)
-        lp->lnd_mobil /= 2;
-    }
-    
-    if (opt_FUEL == 0) { /* just some bits and pieces */
-      if (opt_MOB_ACCESS) {
-       if (lp->lnd_mobil < 0)
-           value = lp->lnd_mobil + (2 * ((float)etus * land_mob_scale));
-       else
-           value = lp->lnd_mobil + ((float)etus * land_mob_scale);
-      } else {
-       value = lp->lnd_mobil + ((float)etus * land_mob_scale);
-      }
-      if (value > land_mob_max)
-       value = land_mob_max;
-      lp->lnd_mobil = value;
+    if (CANT_HAPPEN(etus < 0))
+       etus = 0;
 
-      return; /* Done! */
-    }
-    
-    /* opt_FUEL in force ... */
-    if (lp->lnd_fuelu == 0){
-      if (opt_MOB_ACCESS) {
-       if (lp->lnd_mobil < 0)
-           value = lp->lnd_mobil + (2 * ((float)etus * land_mob_scale));
-       else
-           value = lp->lnd_mobil + ((float)etus * land_mob_scale);
-      } else {
-       value = lp->lnd_mobil + ((float)etus * land_mob_scale);
-      }
-      if (value > land_mob_max)
-       value = land_mob_max;
-      lp->lnd_mobil = value;
-
-    } else {
-       
-      can_add = land_mob_max - lp->lnd_mobil;      
-       
-        if (can_add > ((float)etus*land_mob_scale))
-            can_add = ((float)etus*land_mob_scale);
-
-        have_fuel_for = (lp->lnd_fuel /
-                         lp->lnd_fuelu)*fuel_mult;
-
-        if (can_add > have_fuel_for){
-            int     need;
-            need = can_add - have_fuel_for;
-            d = (double)need;
-            d *= (double)lp->lnd_fuelu;
-            d /= (double)fuel_mult;
-            d /= 5.0;
-            if ((d-(int)d) > 0.0)
-                d++;
-            need = (int)d;
-            newfuel = supply_commod(lp->lnd_own,lp->lnd_x,
-                                    lp->lnd_y,I_PETROL,need);
-            lp->lnd_fuel += (u_char)(newfuel * 5);
-        }
-
-        have_fuel_for = (lp->lnd_fuel /
-                         lp->lnd_fuelu)*fuel_mult;
-
-        if (can_add > have_fuel_for){
-            int     need;
-            need = can_add - have_fuel_for;
-            d = (double)need;
-            d *= (double)lp->lnd_fuelu;
-            d /= (double)fuel_mult;
-            d /= 50.0;
-            if ((d-(int)d) > 0.0)
-                d++;
-            need = (int)d;
-            newfuel = supply_commod(lp->lnd_own,lp->lnd_x,
-                                    lp->lnd_y,I_OIL,need);
-            lp->lnd_fuel += (u_char)(newfuel * 50);
-        }
-
-        have_fuel_for = (lp->lnd_fuel /
-                         lp->lnd_fuelu)*fuel_mult;
-
-        if (can_add > have_fuel_for){
-            total_add = have_fuel_for;
-        }
-        else
-            total_add = can_add;
-        d = (double)total_add;
-        d *= (double)lp->lnd_fuelu;
-        d /= (double)fuel_mult;
-        lp->lnd_fuel -= (u_char)ldround(d,1);
-        lp->lnd_fuel = (u_char)min(lp->lnd_fuel,
-                           lp->lnd_fuelc);
-       if(total_add + lp->lnd_mobil > land_mob_max) {
-           total_add = land_mob_max - lp->lnd_mobil;
-       }
-       
-       if (opt_MOB_ACCESS) {
-         if (lp->lnd_mobil < 0)
-           lp->lnd_mobil += (s_char)total_add;
+    if (lp->lnd_own == 0)
+       return;
+
+    value = lp->lnd_mobil + ((float)etus * land_mob_scale);
+    if (value > land_mob_max) {
+       if (lp->lnd_harden < land_mob_max && !opt_MOB_ACCESS) {
+           /*
+            * Automatic fortification on excess mobility.
+            * Disabled for MOB_ACCESS, because it leads to
+            * excessively deep recursion and thus miserable
+            * performance as the number of land units grows.
+            *
+            * Provide mobility to be used in lnd_fortify()
+            * without overflowing lnd_mobil.
+            */
+           lp->lnd_mobil = land_mob_max;
+           lnd_fortify(lp, value - land_mob_max);
        }
-        lp->lnd_mobil += (s_char)total_add;
+       value = land_mob_max;
     }
+    lp->lnd_mobil = value;
 }
 
 void
-mob_plane(register int etus)
+mob_plane(void)
 {
-       register struct plnstr *pp;
-       register int n;
-       time_t now;
-       
-       time(&now);
-       for (n=0; NULL != (pp = getplanep(n)); n++) {
-           pp->pln_timestamp = now;
-           if (opt_MOB_ACCESS)
-                       pln_do_upd_mob(pp);
-           else
-                       do_mob_plane(pp, etus);
-       }
+    struct plnstr *pp;
+    int n, etus;
+    time_t now;
+
+    time(&now);
+    for (n = 0; NULL != (pp = getplanep(n)); n++) {
+       pp->pln_timestamp = now;
+       if (opt_MOB_ACCESS)
+           etus = game_reset_tick(&pp->pln_access);
+       else
+           etus = etu_per_update;
+       do_mob_plane(pp, etus);
+    }
 }
 
-void
-do_mob_plane(register struct plnstr *pp, register int etus)
+static void
+do_mob_plane(struct plnstr *pp, int etus)
 {
-    extern  int plane_mob_max;
-    extern  float plane_mob_scale;
-    register int value;
+    int value;
+
+    if (CANT_HAPPEN(etus < 0))
+       etus = 0;
 
     if (pp->pln_own == 0)
-        return;
-       if (pp->pln_mobil >= plane_mob_max) {
-               pp->pln_mobil = plane_mob_max;
-               return;
-       }
+       return;
 
     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
     if (value > plane_mob_max)
-        value = plane_mob_max;
+       value = plane_mob_max;
     pp->pln_mobil = value;
 }