]> git.pond.sub.org Git - empserver/blob - src/lib/update/mobility.c
54080b058960189244e316d3aa7c3f7aea535a66
[empserver] / src / lib / update / mobility.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, 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 the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  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 "misc.h"
36 #include "var.h"
37 #include "sect.h"
38 #include "ship.h"
39 #include "land.h"
40 #include "plane.h"
41 #include "nat.h"
42 #include "file.h"
43 #include "optlist.h"
44 #include "mission.h"
45 #include "update.h"
46 #include "gen.h"
47 #include "subs.h"
48 #include "optlist.h"
49
50 extern int update_pending;
51
52 int updating_mob = 1;
53
54 static int timestamp_fixing;
55 static int do_upd_checking = 0;
56
57 static void do_mob_land(register struct lndstr *, register int);
58 static void do_mob_plane(register struct plnstr *, register int);
59 static void do_mob_sect(register struct sctstr *sp, register int etus);
60 static void do_mob_ship(register struct shpstr *, register int);
61
62 static int
63 increase_mob(time_t * counter, float mult)
64 {
65     time_t secs;
66     time_t now;
67     time_t left;
68     extern int updating_mob;
69     int newetus;
70     float newmob;
71     int inewmob;
72
73     time(&now);
74
75     secs = now - *counter;
76     if (secs < 1 || secs < s_p_etu)
77         return 0;
78     newetus = (int)(secs / s_p_etu);
79     if (newetus < 1)
80         return 0;
81     left = (secs % s_p_etu);
82     do {
83         newmob = (float)(newetus * mult);
84         inewmob = (int)(newetus * mult);
85         if (newmob == inewmob || newetus > 7)
86             break;
87         newetus--;
88         left += s_p_etu;
89     } while (newetus > 0);
90     if (newetus <= 0)
91         return 0;
92
93     time(counter);
94     *counter = *counter - left;
95
96     if (updating_mob)
97         return (newetus);
98     return 0;
99 }
100
101 void
102 update_timestamps(time_t lastsavedtime)
103 {
104     struct shpstr *shipp;
105     struct sctstr *sectp;
106     struct lndstr *landp;
107     struct plnstr *planep;
108     int n;
109     time_t now;
110     time_t delta;
111
112     timestamp_fixing = 1;
113     time(&now);
114     delta = now - lastsavedtime;
115     for (n = 0; (shipp = getshipp(n)); n++)
116         shipp->shp_access += delta;
117     for (n = 0; (sectp = getsectid(n)); n++)
118         sectp->sct_access += delta;
119     for (n = 0; (landp = getlandp(n)); n++)
120         landp->lnd_access += delta;
121     for (n = 0; (planep = getplanep(n)); n++)
122         planep->pln_access += delta;
123     timestamp_fixing = 0;
124 }
125
126 void
127 update_all_mob(void)
128 {
129     struct shpstr *shipp;
130     struct sctstr *sectp;
131     struct lndstr *landp;
132     struct plnstr *planep;
133     int n;
134
135     n = 0;
136     while (1) {
137         do_upd_checking = 1;
138         shipp = getshipp(n);
139         sectp = getsectid(n);
140         landp = getlandp(n);
141         planep = getplanep(n);
142         do_upd_checking = 0;
143         if (shipp)
144             shp_do_upd_mob(shipp);
145         if (sectp)
146             sct_do_upd_mob(sectp);
147         if (landp)
148             lnd_do_upd_mob(landp);
149         if (planep)
150             pln_do_upd_mob(planep);
151         if (!shipp && !sectp && !landp && !planep)
152             break;
153         n++;
154     }
155     do_upd_checking = 0;
156 }
157
158 void
159 sct_do_upd_mob(register struct sctstr *sp)
160 {
161     int etus;
162
163     if (do_upd_checking || timestamp_fixing || update_pending)
164         return;
165     if (sp->sct_own == 0)
166         return;
167     if (sp->sct_type == SCT_SANCT)
168         return;
169     if ((etus = increase_mob(&sp->sct_access, sect_mob_scale)) == 0)
170         return;
171     do_upd_checking = 1;
172     do_mob_sect(sp, etus);
173 /*    putsect(sp);*/
174     do_upd_checking = 0;
175 }
176
177 void
178 shp_do_upd_mob(register struct shpstr *sp)
179 {
180     int etus;
181
182     if (do_upd_checking || timestamp_fixing || update_pending)
183         return;
184     if (sp->shp_own == 0)
185         return;
186     if ((etus = increase_mob(&sp->shp_access, ship_mob_scale)) == 0)
187         return;
188     do_upd_checking = 1;
189     do_mob_ship(sp, etus);
190     do_upd_checking = 0;
191 }
192
193 void
194 lnd_do_upd_mob(register struct lndstr *lp)
195 {
196     int etus;
197
198     if (do_upd_checking || timestamp_fixing || update_pending)
199         return;
200     if (lp->lnd_own == 0)
201         return;
202     if ((etus = increase_mob(&lp->lnd_access, land_mob_scale)) == 0)
203         return;
204
205     do_upd_checking = 1;
206     do_mob_land(lp, etus);
207     do_upd_checking = 0;
208 }
209
210 void
211 pln_do_upd_mob(register struct plnstr *pp)
212 {
213     int etus;
214
215     if (do_upd_checking || timestamp_fixing || update_pending)
216         return;
217     if (pp->pln_own == 0)
218         return;
219     if ((etus = increase_mob(&pp->pln_access, plane_mob_scale)) == 0)
220         return;
221
222     do_upd_checking = 1;
223     do_mob_plane(pp, etus);
224     do_upd_checking = 0;
225 }
226
227 void
228 mob_sect(register int etus)
229 {
230     register struct sctstr *sp;
231     register int n;
232     time_t now;
233
234     time(&now);
235     for (n = 0; NULL != (sp = getsectid(n)); n++) {
236         sp->sct_timestamp = now;
237         if (opt_MOB_ACCESS)
238             sct_do_upd_mob(sp);
239         else
240             do_mob_sect(sp, etus);
241     }
242 }
243
244 static void
245 do_mob_sect(register struct sctstr *sp, register int etus)
246 {
247     register int value;
248
249     if (sp->sct_own == 0)
250         return;
251     if (sp->sct_type == SCT_SANCT)
252         return;
253     /* Do we have to even bother? */
254     if (sp->sct_mobil >= sect_mob_max) {
255         /* No, so set just in case and then return */
256         sp->sct_mobil = sect_mob_max;
257         return;
258     }
259     value = sp->sct_mobil + ((float)etus * sect_mob_scale);
260     if (value > sect_mob_max)
261         value = sect_mob_max;
262     sp->sct_mobil = value;
263 }
264
265 void
266 mob_ship(register int etus)
267 {
268     register struct shpstr *sp;
269     register int n;
270     time_t now;
271
272     time(&now);
273     for (n = 0; NULL != (sp = getshipp(n)); n++) {
274         sp->shp_timestamp = now;
275         if (opt_MOB_ACCESS)
276             shp_do_upd_mob(sp);
277         else
278             do_mob_ship(sp, etus);
279     }
280 }
281
282 static void
283 do_mob_ship(register struct shpstr *sp, register int etus)
284 {
285     int newfuel = 0;
286     register int value;
287     int can_add, have_fuel_for, total_add;
288     double d;
289
290     if (sp->shp_own == 0)
291         return;
292
293     /* Do we even have to bother updating this mobility? */
294     if (sp->shp_mobil >= ship_mob_max) {
295         /* No, so don't.  Just set it to max (just in case) and
296            return. */
297         sp->shp_mobil = ship_mob_max;
298         return;
299     }
300
301     if (opt_FUEL == 0) {        /* only a bit to do ... */
302         value = sp->shp_mobil + ((float)etus * ship_mob_scale);
303         if (value > ship_mob_max)
304             value = ship_mob_max;
305         sp->shp_mobil = value;
306         return;                 /* so we ship the FUEL stuff */
307     }
308
309     /* opt_FUEL in force */
310     if (mchr[(int)sp->shp_type].m_fuelu == 0) {
311         value = sp->shp_mobil + ((float)etus * ship_mob_scale);
312         if (value > ship_mob_max)
313             value = ship_mob_max;
314         sp->shp_mobil = (s_char)value;
315     } else {
316         can_add = ship_mob_max - sp->shp_mobil;
317         if (can_add > ((float)etus * ship_mob_scale))
318             can_add = ((float)etus * ship_mob_scale);
319         have_fuel_for = ldround((((double)sp->shp_fuel /
320                                   (double)mchr[(int)sp->shp_type].
321                                   m_fuelu) * (double)fuel_mult), 1);
322
323         if (can_add > have_fuel_for) {
324             int need;
325             need = can_add - have_fuel_for;
326             d = (double)need;
327             d *= (double)mchr[(int)sp->shp_type].m_fuelu;
328             d /= (double)fuel_mult;
329             d /= 5.0;
330             if ((d - (int)d) > 0.0)
331                 d++;
332             need = (int)d;
333             newfuel = supply_commod(sp->shp_own, sp->shp_x,
334                                     sp->shp_y, I_PETROL, need);
335             sp->shp_fuel += (u_char)(newfuel * 5);
336         }
337
338         have_fuel_for = ldround((((double)sp->shp_fuel /
339                                   (double)mchr[(int)sp->shp_type].
340                                   m_fuelu) * (double)fuel_mult), 1);
341
342         if (can_add > have_fuel_for) {
343             int need;
344             need = can_add - have_fuel_for;
345             d = (double)need;
346             d *= (double)mchr[(int)sp->shp_type].m_fuelu;
347             d /= (double)fuel_mult;
348             d /= 50.0;
349             if ((d - (int)d) > 0.0)
350                 d++;
351             need = (int)d;
352             newfuel = supply_commod(sp->shp_own, sp->shp_x,
353                                     sp->shp_y, I_OIL, need);
354             sp->shp_fuel += (u_char)(newfuel * 50);
355         }
356
357         have_fuel_for = ldround((((double)sp->shp_fuel /
358                                   (double)mchr[(int)sp->shp_type].
359                                   m_fuelu) * (double)fuel_mult), 1);
360
361         if (can_add > have_fuel_for)
362             total_add = have_fuel_for;
363         else
364             total_add = can_add;
365         d = (double)total_add;
366         d *= (double)mchr[(int)sp->shp_type].m_fuelu;
367         d /= (double)fuel_mult;
368         sp->shp_fuel -= (u_char)ldround(d, 1);
369         sp->shp_fuel = (u_char)min(sp->shp_fuel,
370                                    mchr[(int)sp->shp_type].m_fuelc);
371         sp->shp_mobil += (s_char)total_add;
372     }
373 }
374
375 void
376 mob_land(register int etus)
377 {
378     register struct lndstr *lp;
379     register int n;
380     time_t now;
381
382     time(&now);
383     for (n = 0; NULL != (lp = getlandp(n)); n++) {
384         lp->lnd_timestamp = now;
385         if (opt_MOB_ACCESS)
386             lnd_do_upd_mob(lp);
387         else
388             do_mob_land(lp, etus);
389     }
390 }
391
392 static void
393 do_mob_land(register struct lndstr *lp, register int etus)
394 {
395     int newfuel = 0;
396     register int value;
397     int can_add, have_fuel_for, total_add;
398     double d;
399
400     if (lp->lnd_own == 0)
401         return;
402
403     if (lp->lnd_mobil >= land_mob_max) {
404         lp->lnd_mobil = land_mob_max;
405         if (lp->lnd_harden >= land_mob_max) {
406             lp->lnd_harden = land_mob_max;
407             return;
408         }
409     }
410
411     if (opt_FUEL == 0) {        /* just some bits and pieces */
412         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
413         if (value > land_mob_max) {
414             lnd_fortify(lp, value - land_mob_max);
415             value = land_mob_max;
416         }
417         lp->lnd_mobil = value;
418
419         return;                 /* Done! */
420     }
421
422     /* opt_FUEL in force ... */
423     if (lp->lnd_fuelu == 0) {
424         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
425         if (value > land_mob_max) {
426             lnd_fortify(lp, value - land_mob_max);
427             value = land_mob_max;
428         }
429         lp->lnd_mobil = value;
430
431     } else {
432
433         can_add = land_mob_max - lp->lnd_mobil;
434
435         if (can_add > ((float)etus * land_mob_scale))
436             can_add = ((float)etus * land_mob_scale);
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 = (double)need;
444             d *= (double)lp->lnd_fuelu;
445             d /= (double)fuel_mult;
446             d /= 5.0;
447             if ((d - (int)d) > 0.0)
448                 d++;
449             need = (int)d;
450             newfuel = supply_commod(lp->lnd_own, lp->lnd_x,
451                                     lp->lnd_y, I_PETROL, need);
452             lp->lnd_fuel += (u_char)(newfuel * 5);
453         }
454
455         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
456
457         if (can_add > have_fuel_for) {
458             int need;
459             need = can_add - have_fuel_for;
460             d = (double)need;
461             d *= (double)lp->lnd_fuelu;
462             d /= (double)fuel_mult;
463             d /= 50.0;
464             if ((d - (int)d) > 0.0)
465                 d++;
466             need = (int)d;
467             newfuel = supply_commod(lp->lnd_own, lp->lnd_x,
468                                     lp->lnd_y, I_OIL, need);
469             lp->lnd_fuel += (u_char)(newfuel * 50);
470         }
471
472         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
473
474         if (can_add > have_fuel_for) {
475             total_add = have_fuel_for;
476         } else
477             total_add = can_add;
478         d = (double)total_add;
479         d *= (double)lp->lnd_fuelu;
480         d /= (double)fuel_mult;
481         lp->lnd_fuel -= (u_char)ldround(d, 1);
482         lp->lnd_fuel = (u_char)min(lp->lnd_fuel, lp->lnd_fuelc);
483         if (total_add + lp->lnd_mobil > land_mob_max) {
484             total_add = land_mob_max - lp->lnd_mobil;
485         }
486         /* no automatic fortification here, as it would cost fuel */
487
488         lp->lnd_mobil += (s_char)total_add;
489     }
490 }
491
492 void
493 mob_plane(register int etus)
494 {
495     register struct plnstr *pp;
496     register int n;
497     time_t now;
498
499     time(&now);
500     for (n = 0; NULL != (pp = getplanep(n)); n++) {
501         pp->pln_timestamp = now;
502         if (opt_MOB_ACCESS)
503             pln_do_upd_mob(pp);
504         else
505             do_mob_plane(pp, etus);
506     }
507 }
508
509 static void
510 do_mob_plane(register struct plnstr *pp, register int etus)
511 {
512     register int value;
513
514     if (pp->pln_own == 0)
515         return;
516     if (pp->pln_mobil >= plane_mob_max) {
517         pp->pln_mobil = plane_mob_max;
518         return;
519     }
520
521     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
522     if (value > plane_mob_max)
523         value = plane_mob_max;
524     pp->pln_mobil = value;
525 }