]> git.pond.sub.org Git - empserver/blob - src/lib/update/mobility.c
(do_mob_sect, do_mob_plane): Remove the special case for maxed out
[empserver] / src / lib / update / mobility.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  mobility.c: Add mobility to each of the items which accumulate mobility.
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1986
32  *     Steve McClure, 1998-1999
33  */
34
35 #include <config.h>
36
37 #include "land.h"
38 #include "plane.h"
39 #include "server.h"
40 #include "ship.h"
41 #include "update.h"
42
43
44 int updating_mob = 1;
45
46 static int timestamp_fixing;
47 static int do_upd_checking = 0;
48
49 static void do_mob_land(struct lndstr *, int);
50 static void do_mob_plane(struct plnstr *, int);
51 static void do_mob_sect(struct sctstr *sp, int etus);
52 static void do_mob_ship(struct shpstr *, int);
53
54 static int
55 increase_mob(time_t *counter, float mult)
56 {
57     time_t secs;
58     time_t now;
59     time_t left;
60     int newetus;
61     float newmob;
62     int inewmob;
63
64     time(&now);
65
66     secs = now - *counter;
67     if (secs < 1 || secs < s_p_etu)
68         return 0;
69     newetus = (int)(secs / s_p_etu);
70     if (newetus < 1)
71         return 0;
72     left = (secs % s_p_etu);
73     do {
74         newmob = newetus * mult;
75         inewmob = (int)newmob;
76         if (newmob == inewmob || newetus > 7)
77             break;
78         newetus--;
79         left += s_p_etu;
80     } while (newetus > 0);
81     if (newetus <= 0)
82         return 0;
83
84     *counter = now - left;
85
86     if (updating_mob)
87         return newetus;
88     return 0;
89 }
90
91 void
92 update_timestamps(time_t lastsavedtime)
93 {
94     struct shpstr *shipp;
95     struct sctstr *sectp;
96     struct lndstr *landp;
97     struct plnstr *planep;
98     int n;
99     time_t now;
100     time_t delta;
101
102     timestamp_fixing = 1;
103     time(&now);
104     delta = now - lastsavedtime;
105     for (n = 0; (shipp = getshipp(n)); n++)
106         shipp->shp_access += delta;
107     for (n = 0; (sectp = getsectid(n)); n++)
108         sectp->sct_access += delta;
109     for (n = 0; (landp = getlandp(n)); n++)
110         landp->lnd_access += delta;
111     for (n = 0; (planep = getplanep(n)); n++)
112         planep->pln_access += delta;
113     timestamp_fixing = 0;
114 }
115
116 void
117 update_all_mob(void)
118 {
119     struct shpstr *shipp;
120     struct sctstr *sectp;
121     struct lndstr *landp;
122     struct plnstr *planep;
123     int n;
124
125     n = 0;
126     while (1) {
127         do_upd_checking = 1;
128         shipp = getshipp(n);
129         sectp = getsectid(n);
130         landp = getlandp(n);
131         planep = getplanep(n);
132         do_upd_checking = 0;
133         if (shipp)
134             shp_do_upd_mob(shipp);
135         if (sectp)
136             sct_do_upd_mob(sectp);
137         if (landp)
138             lnd_do_upd_mob(landp);
139         if (planep)
140             pln_do_upd_mob(planep);
141         if (!shipp && !sectp && !landp && !planep)
142             break;
143         n++;
144     }
145     do_upd_checking = 0;
146 }
147
148 void
149 sct_do_upd_mob(struct sctstr *sp)
150 {
151     int etus;
152
153     if (do_upd_checking || timestamp_fixing || update_pending)
154         return;
155     if (sp->sct_own == 0)
156         return;
157     if (sp->sct_type == SCT_SANCT)
158         return;
159     if ((etus = increase_mob(&sp->sct_access, sect_mob_scale)) == 0)
160         return;
161     do_upd_checking = 1;
162     do_mob_sect(sp, etus);
163 /*    putsect(sp);*/
164     do_upd_checking = 0;
165 }
166
167 void
168 shp_do_upd_mob(struct shpstr *sp)
169 {
170     int etus;
171
172     if (do_upd_checking || timestamp_fixing || update_pending)
173         return;
174     if (sp->shp_own == 0)
175         return;
176     if ((etus = increase_mob(&sp->shp_access, ship_mob_scale)) == 0)
177         return;
178     do_upd_checking = 1;
179     do_mob_ship(sp, etus);
180     do_upd_checking = 0;
181 }
182
183 void
184 lnd_do_upd_mob(struct lndstr *lp)
185 {
186     int etus;
187
188     if (do_upd_checking || timestamp_fixing || update_pending)
189         return;
190     if (lp->lnd_own == 0)
191         return;
192     if ((etus = increase_mob(&lp->lnd_access, land_mob_scale)) == 0)
193         return;
194
195     do_upd_checking = 1;
196     do_mob_land(lp, etus);
197     do_upd_checking = 0;
198 }
199
200 void
201 pln_do_upd_mob(struct plnstr *pp)
202 {
203     int etus;
204
205     if (do_upd_checking || timestamp_fixing || update_pending)
206         return;
207     if (pp->pln_own == 0)
208         return;
209     if ((etus = increase_mob(&pp->pln_access, plane_mob_scale)) == 0)
210         return;
211
212     do_upd_checking = 1;
213     do_mob_plane(pp, etus);
214     do_upd_checking = 0;
215 }
216
217 void
218 mob_sect(int etus)
219 {
220     struct sctstr *sp;
221     int n;
222     time_t now;
223
224     time(&now);
225     for (n = 0; NULL != (sp = getsectid(n)); n++) {
226         sp->sct_timestamp = now;
227         if (opt_MOB_ACCESS)
228             sct_do_upd_mob(sp);
229         else
230             do_mob_sect(sp, etus);
231     }
232 }
233
234 static void
235 do_mob_sect(struct sctstr *sp, int etus)
236 {
237     int value;
238
239     if (sp->sct_own == 0)
240         return;
241     if (sp->sct_type == SCT_SANCT)
242         return;
243
244     value = sp->sct_mobil + ((float)etus * sect_mob_scale);
245     if (value > sect_mob_max)
246         value = sect_mob_max;
247     sp->sct_mobil = value;
248 }
249
250 void
251 mob_ship(int etus)
252 {
253     struct shpstr *sp;
254     int n;
255     time_t now;
256
257     time(&now);
258     for (n = 0; NULL != (sp = getshipp(n)); n++) {
259         sp->shp_timestamp = now;
260         if (opt_MOB_ACCESS)
261             shp_do_upd_mob(sp);
262         else
263             do_mob_ship(sp, etus);
264     }
265 }
266
267 static void
268 do_mob_ship(struct shpstr *sp, int etus)
269 {
270     int newfuel = 0;
271     int value;
272     int can_add, have_fuel_for, total_add;
273     double d;
274
275     if (sp->shp_own == 0)
276         return;
277
278     if (opt_FUEL == 0 || mchr[(int)sp->shp_type].m_fuelu == 0) {
279         value = sp->shp_mobil + (float)etus * ship_mob_scale;
280         if (value > ship_mob_max)
281             value = ship_mob_max;
282         sp->shp_mobil = (signed char)value;
283     } else {
284         if (sp->shp_mobil >= ship_mob_max) {
285             sp->shp_mobil = ship_mob_max;
286             return;
287         }
288         can_add = ship_mob_max - sp->shp_mobil;
289         if (can_add > (float)etus * ship_mob_scale)
290             can_add = (float)etus * ship_mob_scale;
291         have_fuel_for = ldround(((double)sp->shp_fuel /
292                                  (double)mchr[(int)sp->shp_type].m_fuelu)
293                                 * (double)fuel_mult, 1);
294
295         if (can_add > have_fuel_for) {
296             int need;
297             need = can_add - have_fuel_for;
298             d = need;
299             d *= mchr[(int)sp->shp_type].m_fuelu;
300             d /= fuel_mult;
301             d /= 5.0;
302             if (d - (int)d > 0.0)
303                 d++;
304             need = (int)d;
305             newfuel = supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
306                                     I_PETROL, need);
307             sp->shp_fuel += newfuel * 5;
308         }
309
310         have_fuel_for = ldround(((double)sp->shp_fuel /
311                                  (double)mchr[(int)sp->shp_type].m_fuelu)
312                                 * (double)fuel_mult, 1);
313
314         if (can_add > have_fuel_for) {
315             int need;
316             need = can_add - have_fuel_for;
317             d = need;
318             d *= mchr[(int)sp->shp_type].m_fuelu;
319             d /= fuel_mult;
320             d /= 50.0;
321             if (d - (int)d > 0.0)
322                 d++;
323             need = (int)d;
324             newfuel = supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
325                                     I_OIL, need);
326             sp->shp_fuel += newfuel * 50;
327         }
328
329         have_fuel_for = ldround(((double)sp->shp_fuel /
330                                  (double)mchr[(int)sp->shp_type].m_fuelu)
331                                 * (double)fuel_mult, 1);
332
333         if (can_add > have_fuel_for)
334             total_add = have_fuel_for;
335         else
336             total_add = can_add;
337         d = total_add;
338         d *= mchr[(int)sp->shp_type].m_fuelu;
339         d /= fuel_mult;
340         sp->shp_fuel -= ldround(d, 1);
341         sp->shp_fuel = MIN(sp->shp_fuel, mchr[(int)sp->shp_type].m_fuelc);
342         sp->shp_mobil += total_add;
343     }
344 }
345
346 void
347 mob_land(int etus)
348 {
349     struct lndstr *lp;
350     int n;
351     time_t now;
352
353     time(&now);
354     for (n = 0; NULL != (lp = getlandp(n)); n++) {
355         lp->lnd_timestamp = now;
356         if (opt_MOB_ACCESS)
357             lnd_do_upd_mob(lp);
358         else
359             do_mob_land(lp, etus);
360     }
361 }
362
363 static void
364 do_mob_land(struct lndstr *lp, int etus)
365 {
366     int newfuel = 0;
367     int value;
368     int can_add, have_fuel_for, total_add;
369     double d;
370
371     if (lp->lnd_own == 0)
372         return;
373
374     if (opt_FUEL == 0 || lp->lnd_fuelu == 0) {
375         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
376         if (value > land_mob_max) {
377             if (lp->lnd_harden < land_mob_max && !opt_MOB_ACCESS) {
378                 /*
379                  * Automatic fortification on excess mobility.
380                  * Disabled for MOB_ACCESS, because it leads to
381                  * excessively deep recursion and thus miserable
382                  * performance as the number of land units grows.
383                  *
384                  * Provide mobility to be used in lnd_fortify()
385                  * without overflowing lnd_mobil.
386                  */
387                 lp->lnd_mobil = land_mob_max;
388                 lnd_fortify(lp, value - land_mob_max);
389             }
390             value = land_mob_max;
391         }
392         lp->lnd_mobil = value;
393
394     } else {
395         if (lp->lnd_mobil >= land_mob_max) {
396             lp->lnd_mobil = land_mob_max;
397             return;
398         }
399
400         can_add = land_mob_max - lp->lnd_mobil;
401
402         if (can_add > (float)etus * land_mob_scale)
403             can_add = (float)etus * land_mob_scale;
404
405         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
406
407         if (can_add > have_fuel_for) {
408             int need;
409             need = can_add - have_fuel_for;
410             d = need;
411             d *= lp->lnd_fuelu;
412             d /= fuel_mult;
413             d /= 5.0;
414             if (d - (int)d > 0.0)
415                 d++;
416             need = (int)d;
417             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
418                                     I_PETROL, need);
419             lp->lnd_fuel += newfuel * 5;
420         }
421
422         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
423
424         if (can_add > have_fuel_for) {
425             int need;
426             need = can_add - have_fuel_for;
427             d = need;
428             d *= lp->lnd_fuelu;
429             d /= fuel_mult;
430             d /= 50.0;
431             if (d - (int)d > 0.0)
432                 d++;
433             need = (int)d;
434             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
435                                     I_OIL, need);
436             lp->lnd_fuel += newfuel * 50;
437         }
438
439         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
440
441         if (can_add > have_fuel_for) {
442             total_add = have_fuel_for;
443         } else
444             total_add = can_add;
445         d = total_add;
446         d *= lp->lnd_fuelu;
447         d /= fuel_mult;
448         lp->lnd_fuel -= ldround(d, 1);
449         lp->lnd_fuel = MIN(lp->lnd_fuel, lp->lnd_fuelc);
450         lp->lnd_mobil += total_add;
451         /* No excess mobility here, hence no automatic fortification */
452     }
453 }
454
455 void
456 mob_plane(int etus)
457 {
458     struct plnstr *pp;
459     int n;
460     time_t now;
461
462     time(&now);
463     for (n = 0; NULL != (pp = getplanep(n)); n++) {
464         pp->pln_timestamp = now;
465         if (opt_MOB_ACCESS)
466             pln_do_upd_mob(pp);
467         else
468             do_mob_plane(pp, etus);
469     }
470 }
471
472 static void
473 do_mob_plane(struct plnstr *pp, int etus)
474 {
475     int value;
476
477     if (pp->pln_own == 0)
478         return;
479
480     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
481     if (value > plane_mob_max)
482         value = plane_mob_max;
483     pp->pln_mobil = value;
484 }