]> git.pond.sub.org Git - empserver/blobdiff - src/lib/update/mobility.c
Update copyright notice
[empserver] / src / lib / update / mobility.c
index 1de65bc5ac163c1b82ccac59c26194e4b66beb98..73330f6cef9da5855468b19079b3ea495694206f 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2006, 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,
@@ -14,8 +14,7 @@
  *  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/>.
  *
  *  ---
  *
  *  ---
  *
  *  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 <config.h>
 
+#include "game.h"
 #include "land.h"
 #include "plane.h"
 #include "server.h"
 #include "ship.h"
 #include "update.h"
 
-
-int updating_mob = 1;
-
-static int timestamp_fixing;
-static int do_upd_checking = 0;
+static int do_upd_checking;
 
 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);
 
-static int
-increase_mob(time_t *counter, float mult)
-{
-    time_t secs;
-    time_t now;
-    time_t left;
-    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 = newetus * mult;
-       inewmob = (int)newmob;
-       if (newmob == inewmob || newetus > 7)
-           break;
-       newetus--;
-       left += s_p_etu;
-    } while (newetus > 0);
-    if (newetus <= 0)
-       return 0;
-
-    *counter = now - left;
-
-    if (updating_mob)
-       return newetus;
-    return 0;
-}
-
-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;
-}
-
-void
-update_all_mob(void)
-{
-    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(struct sctstr *sp)
 {
     int etus;
 
-    if (do_upd_checking || timestamp_fixing || update_pending)
+    if (do_upd_checking || update_running)
        return;
     if (sp->sct_own == 0)
        return;
     if (sp->sct_type == SCT_SANCT)
        return;
-    if ((etus = increase_mob(&sp->sct_access, sect_mob_scale)) == 0)
+    etus = game_tick_to_now(&sp->sct_access);
+    if (etus == 0)
        return;
-    do_upd_checking = 1;
+
+    do_upd_checking = 1;       /* avoid recursion */
     do_mob_sect(sp, etus);
-/*    putsect(sp);*/
     do_upd_checking = 0;
 }
 
@@ -169,13 +73,15 @@ shp_do_upd_mob(struct shpstr *sp)
 {
     int etus;
 
-    if (do_upd_checking || timestamp_fixing || update_pending)
+    if (do_upd_checking || update_running)
        return;
     if (sp->shp_own == 0)
        return;
-    if ((etus = increase_mob(&sp->shp_access, ship_mob_scale)) == 0)
+    etus = game_tick_to_now(&sp->shp_access);
+    if (etus == 0)
        return;
-    do_upd_checking = 1;
+
+    do_upd_checking = 1;       /* avoid recursion */
     do_mob_ship(sp, etus);
     do_upd_checking = 0;
 }
@@ -185,14 +91,15 @@ lnd_do_upd_mob(struct lndstr *lp)
 {
     int etus;
 
-    if (do_upd_checking || timestamp_fixing || update_pending)
+    if (do_upd_checking || update_running)
        return;
     if (lp->lnd_own == 0)
        return;
-    if ((etus = increase_mob(&lp->lnd_access, land_mob_scale)) == 0)
+    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;
 }
@@ -202,32 +109,34 @@ pln_do_upd_mob(struct plnstr *pp)
 {
     int etus;
 
-    if (do_upd_checking || timestamp_fixing || update_pending)
+    if (do_upd_checking || update_running)
        return;
     if (pp->pln_own == 0)
        return;
-    if ((etus = increase_mob(&pp->pln_access, plane_mob_scale)) == 0)
+    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(int etus)
+mob_sect(void)
 {
     struct sctstr *sp;
-    int n;
+    int n, etus;
     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);
+           etus = game_reset_tick(&sp->sct_access);
        else
-           do_mob_sect(sp, etus);
+           etus = etu_per_update;
+       do_mob_sect(sp, etus);
     }
 }
 
@@ -236,16 +145,14 @@ do_mob_sect(struct sctstr *sp, int etus)
 {
     int value;
 
+    if (CANT_HAPPEN(etus < 0))
+       etus = 0;
+
     if (sp->sct_own == 0)
        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;
@@ -253,253 +160,104 @@ do_mob_sect(struct sctstr *sp, int etus)
 }
 
 void
-mob_ship(int etus)
+mob_ship(void)
 {
     struct shpstr *sp;
-    int n;
+    int n, etus;
     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);
+           etus = game_reset_tick(&sp->shp_access);
        else
-           do_mob_ship(sp, etus);
+           etus = etu_per_update;
+       do_mob_ship(sp, etus);
     }
 }
 
 static void
 do_mob_ship(struct shpstr *sp, int etus)
 {
-    int newfuel = 0;
     int value;
-    int can_add, have_fuel_for, total_add;
-    double d;
 
-    if (sp->shp_own == 0)
-       return;
+    if (CANT_HAPPEN(etus < 0))
+       etus = 0;
 
-    /* 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;
+    if (sp->shp_own == 0)
        return;
-    }
-
-    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 */
-    }
-
-    /* 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 = (signed 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 = need;
-           d *= mchr[(int)sp->shp_type].m_fuelu;
-           d /= 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 += 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 = need;
-           d *= mchr[(int)sp->shp_type].m_fuelu;
-           d /= 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 += 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 = total_add;
-       d *= mchr[(int)sp->shp_type].m_fuelu;
-       d /= fuel_mult;
-       sp->shp_fuel -= ldround(d, 1);
-       sp->shp_fuel = MIN(sp->shp_fuel, mchr[(int)sp->shp_type].m_fuelc);
-       sp->shp_mobil += 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(int etus)
+mob_land(void)
 {
     struct lndstr *lp;
-    int n;
+    int n, etus;
     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);
+           etus = game_reset_tick(&lp->lnd_access);
        else
-           do_mob_land(lp, etus);
+           etus = etu_per_update;
+       do_mob_land(lp, etus);
     }
 }
 
 static void
 do_mob_land(struct lndstr *lp, int etus)
 {
-    int newfuel = 0;
     int value;
-    int can_add, have_fuel_for, total_add;
-    double d;
+
+    if (CANT_HAPPEN(etus < 0))
+       etus = 0;
 
     if (lp->lnd_own == 0)
        return;
 
-    if (lp->lnd_mobil >= land_mob_max) {
-       lp->lnd_mobil = land_mob_max;
-       if (lp->lnd_harden >= land_mob_max) {
-           lp->lnd_harden = land_mob_max;
-           return;
-       }
-    }
-
-    if (opt_FUEL == 0) {       /* just some bits and pieces */
-       value = lp->lnd_mobil + ((float)etus * land_mob_scale);
-       if (value > land_mob_max) {
-           /*
-            * provide mobility to be used in lnd_fortify()
-            * without overflowing lnd_mobil
-            */
-           lp->lnd_mobil = land_mob_max;
-           if (!opt_MOB_ACCESS)
-               lnd_fortify(lp, value - land_mob_max);
-           lp->lnd_mobil = land_mob_max;
-       } else
-           lp->lnd_mobil = value;
-
-       return;                 /* Done! */
-    }
-
-    /* opt_FUEL in force ... */
-    if (lp->lnd_fuelu == 0) {
-       value = lp->lnd_mobil + ((float)etus * land_mob_scale);
-       if (value > land_mob_max) {
+    value = lp->lnd_mobil + ((float)etus * land_mob_scale);
+    if (value > land_mob_max) {
+       if (lp->lnd_harden < land_mob_max && !opt_MOB_ACCESS) {
            /*
-            * provide mobility to be used in lnd_fortify()
-            * without overflowing lnd_mobil
+            * 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;
-           if (!opt_MOB_ACCESS)
-               lnd_fortify(lp, value - land_mob_max);
-           lp->lnd_mobil = land_mob_max;
-       } else
-           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 = need;
-           d *= lp->lnd_fuelu;
-           d /= 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 += 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 = need;
-           d *= lp->lnd_fuelu;
-           d /= 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 += newfuel * 50;
+           lnd_fortify(lp, value - land_mob_max);
        }
-
-       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 = total_add;
-       d *= lp->lnd_fuelu;
-       d /= fuel_mult;
-       lp->lnd_fuel -= ldround(d, 1);
-       lp->lnd_fuel = MIN(lp->lnd_fuel, lp->lnd_fuelc);
-       lp->lnd_mobil += total_add;
-       /* No excess mobility here, hence no automatic fortification */
+       value = land_mob_max;
     }
+    lp->lnd_mobil = value;
 }
 
 void
-mob_plane(int etus)
+mob_plane(void)
 {
     struct plnstr *pp;
-    int n;
+    int n, etus;
     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);
+           etus = game_reset_tick(&pp->pln_access);
        else
-           do_mob_plane(pp, etus);
+           etus = etu_per_update;
+       do_mob_plane(pp, etus);
     }
 }
 
@@ -508,12 +266,11 @@ do_mob_plane(struct plnstr *pp, int etus)
 {
     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;
-    }
 
     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
     if (value > plane_mob_max)