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