]> git.pond.sub.org Git - empserver/blob - src/lib/update/mobility.c
Update copyright notice.
[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     /* Do we have to even bother? */
244     if (sp->sct_mobil >= sect_mob_max) {
245         /* No, so set just in case and then return */
246         sp->sct_mobil = sect_mob_max;
247         return;
248     }
249     value = sp->sct_mobil + ((float)etus * sect_mob_scale);
250     if (value > sect_mob_max)
251         value = sect_mob_max;
252     sp->sct_mobil = value;
253 }
254
255 void
256 mob_ship(int etus)
257 {
258     struct shpstr *sp;
259     int n;
260     time_t now;
261
262     time(&now);
263     for (n = 0; NULL != (sp = getshipp(n)); n++) {
264         sp->shp_timestamp = now;
265         if (opt_MOB_ACCESS)
266             shp_do_upd_mob(sp);
267         else
268             do_mob_ship(sp, etus);
269     }
270 }
271
272 static void
273 do_mob_ship(struct shpstr *sp, int etus)
274 {
275     int newfuel = 0;
276     int value;
277     int can_add, have_fuel_for, total_add;
278     double d;
279
280     if (sp->shp_own == 0)
281         return;
282
283     /* Do we even have to bother updating this mobility? */
284     if (sp->shp_mobil >= ship_mob_max) {
285         /* No, so don't.  Just set it to max (just in case) and
286            return. */
287         sp->shp_mobil = ship_mob_max;
288         return;
289     }
290
291     if (opt_FUEL == 0) {        /* only a bit to do ... */
292         value = sp->shp_mobil + ((float)etus * ship_mob_scale);
293         if (value > ship_mob_max)
294             value = ship_mob_max;
295         sp->shp_mobil = value;
296         return;                 /* so we ship the FUEL stuff */
297     }
298
299     /* opt_FUEL in force */
300     if (mchr[(int)sp->shp_type].m_fuelu == 0) {
301         value = sp->shp_mobil + (float)etus * ship_mob_scale;
302         if (value > ship_mob_max)
303             value = ship_mob_max;
304         sp->shp_mobil = (signed char)value;
305     } else {
306         can_add = ship_mob_max - sp->shp_mobil;
307         if (can_add > (float)etus * ship_mob_scale)
308             can_add = (float)etus * ship_mob_scale;
309         have_fuel_for = ldround(((double)sp->shp_fuel /
310                                  (double)mchr[(int)sp->shp_type].m_fuelu)
311                                 * (double)fuel_mult, 1);
312
313         if (can_add > have_fuel_for) {
314             int need;
315             need = can_add - have_fuel_for;
316             d = need;
317             d *= mchr[(int)sp->shp_type].m_fuelu;
318             d /= fuel_mult;
319             d /= 5.0;
320             if (d - (int)d > 0.0)
321                 d++;
322             need = (int)d;
323             newfuel = supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
324                                     I_PETROL, need);
325             sp->shp_fuel += newfuel * 5;
326         }
327
328         have_fuel_for = ldround(((double)sp->shp_fuel /
329                                  (double)mchr[(int)sp->shp_type].m_fuelu)
330                                 * (double)fuel_mult, 1);
331
332         if (can_add > have_fuel_for) {
333             int need;
334             need = can_add - have_fuel_for;
335             d = need;
336             d *= mchr[(int)sp->shp_type].m_fuelu;
337             d /= fuel_mult;
338             d /= 50.0;
339             if (d - (int)d > 0.0)
340                 d++;
341             need = (int)d;
342             newfuel = supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
343                                     I_OIL, need);
344             sp->shp_fuel += newfuel * 50;
345         }
346
347         have_fuel_for = ldround(((double)sp->shp_fuel /
348                                  (double)mchr[(int)sp->shp_type].m_fuelu)
349                                 * (double)fuel_mult, 1);
350
351         if (can_add > have_fuel_for)
352             total_add = have_fuel_for;
353         else
354             total_add = can_add;
355         d = total_add;
356         d *= mchr[(int)sp->shp_type].m_fuelu;
357         d /= fuel_mult;
358         sp->shp_fuel -= ldround(d, 1);
359         sp->shp_fuel = MIN(sp->shp_fuel, mchr[(int)sp->shp_type].m_fuelc);
360         sp->shp_mobil += total_add;
361     }
362 }
363
364 void
365 mob_land(int etus)
366 {
367     struct lndstr *lp;
368     int n;
369     time_t now;
370
371     time(&now);
372     for (n = 0; NULL != (lp = getlandp(n)); n++) {
373         lp->lnd_timestamp = now;
374         if (opt_MOB_ACCESS)
375             lnd_do_upd_mob(lp);
376         else
377             do_mob_land(lp, etus);
378     }
379 }
380
381 static void
382 do_mob_land(struct lndstr *lp, int etus)
383 {
384     int newfuel = 0;
385     int value;
386     int can_add, have_fuel_for, total_add;
387     double d;
388
389     if (lp->lnd_own == 0)
390         return;
391
392     if (lp->lnd_mobil >= land_mob_max) {
393         lp->lnd_mobil = land_mob_max;
394         if (lp->lnd_harden >= land_mob_max) {
395             lp->lnd_harden = land_mob_max;
396             return;
397         }
398     }
399
400     if (opt_FUEL == 0 || lp->lnd_fuelu == 0) {
401         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
402         if (value > land_mob_max) {
403             /*
404              * provide mobility to be used in lnd_fortify()
405              * without overflowing lnd_mobil
406              */
407             lp->lnd_mobil = land_mob_max;
408             if (!opt_MOB_ACCESS)
409                 lnd_fortify(lp, value - land_mob_max);
410             lp->lnd_mobil = land_mob_max;
411         } else
412             lp->lnd_mobil = value;
413
414     } else {
415
416         can_add = land_mob_max - lp->lnd_mobil;
417
418         if (can_add > (float)etus * land_mob_scale)
419             can_add = (float)etus * land_mob_scale;
420
421         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
422
423         if (can_add > have_fuel_for) {
424             int need;
425             need = can_add - have_fuel_for;
426             d = need;
427             d *= lp->lnd_fuelu;
428             d /= fuel_mult;
429             d /= 5.0;
430             if (d - (int)d > 0.0)
431                 d++;
432             need = (int)d;
433             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
434                                     I_PETROL, need);
435             lp->lnd_fuel += newfuel * 5;
436         }
437
438         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
439
440         if (can_add > have_fuel_for) {
441             int need;
442             need = can_add - have_fuel_for;
443             d = need;
444             d *= lp->lnd_fuelu;
445             d /= fuel_mult;
446             d /= 50.0;
447             if (d - (int)d > 0.0)
448                 d++;
449             need = (int)d;
450             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
451                                     I_OIL, need);
452             lp->lnd_fuel += newfuel * 50;
453         }
454
455         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
456
457         if (can_add > have_fuel_for) {
458             total_add = have_fuel_for;
459         } else
460             total_add = can_add;
461         d = total_add;
462         d *= lp->lnd_fuelu;
463         d /= fuel_mult;
464         lp->lnd_fuel -= ldround(d, 1);
465         lp->lnd_fuel = MIN(lp->lnd_fuel, lp->lnd_fuelc);
466         lp->lnd_mobil += total_add;
467         /* No excess mobility here, hence no automatic fortification */
468     }
469 }
470
471 void
472 mob_plane(int etus)
473 {
474     struct plnstr *pp;
475     int n;
476     time_t now;
477
478     time(&now);
479     for (n = 0; NULL != (pp = getplanep(n)); n++) {
480         pp->pln_timestamp = now;
481         if (opt_MOB_ACCESS)
482             pln_do_upd_mob(pp);
483         else
484             do_mob_plane(pp, etus);
485     }
486 }
487
488 static void
489 do_mob_plane(struct plnstr *pp, int etus)
490 {
491     int value;
492
493     if (pp->pln_own == 0)
494         return;
495     if (pp->pln_mobil >= plane_mob_max) {
496         pp->pln_mobil = plane_mob_max;
497         return;
498     }
499
500     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
501     if (value > plane_mob_max)
502         value = plane_mob_max;
503     pp->pln_mobil = value;
504 }