]> git.pond.sub.org Git - empserver/blob - src/lib/update/mobility.c
Indented with src/scripts/indent-emp.
[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 timestamp_fixing;
51 extern int update_pending;
52 int do_upd_checking = 0;
53
54
55 int
56 increase_mob(time_t * counter, float mult)
57 {
58     time_t secs;
59     time_t now;
60     time_t left;
61     extern long s_p_etu;
62     extern int updating_mob;
63     int newetus;
64     float newmob;
65     int inewmob;
66
67     time(&now);
68
69     secs = now - *counter;
70     if (secs < 1 || secs < s_p_etu)
71         return 0;
72     newetus = (int)(secs / s_p_etu);
73     if (newetus < 1)
74         return 0;
75     left = (secs % s_p_etu);
76     do {
77         newmob = (float)(newetus * mult);
78         inewmob = (int)(newetus * mult);
79         if (newmob == inewmob || newetus > 7)
80             break;
81         newetus--;
82         left += s_p_etu;
83     } while (newetus > 0);
84     if (newetus <= 0)
85         return 0;
86
87     time(counter);
88     *counter = *counter - left;
89
90     if (updating_mob)
91         return (newetus);
92     return 0;
93 }
94
95 void
96 update_timestamps(time_t lastsavedtime)
97 {
98     struct shpstr *shipp;
99     struct sctstr *sectp;
100     struct lndstr *landp;
101     struct plnstr *planep;
102     int n;
103     time_t now;
104     time_t delta;
105
106     timestamp_fixing = 1;
107     time(&now);
108     delta = now - lastsavedtime;
109     for (n = 0; (shipp = getshipp(n)); n++)
110         shipp->shp_access += delta;
111     for (n = 0; (sectp = getsectid(n)); n++)
112         sectp->sct_access += delta;
113     for (n = 0; (landp = getlandp(n)); n++)
114         landp->lnd_access += delta;
115     for (n = 0; (planep = getplanep(n)); n++)
116         planep->pln_access += delta;
117     timestamp_fixing = 0;
118 }
119
120 void
121 update_all_mob(void)
122 {
123     struct shpstr *shipp;
124     struct sctstr *sectp;
125     struct lndstr *landp;
126     struct plnstr *planep;
127     int n;
128
129     n = 0;
130     while (1) {
131         do_upd_checking = 1;
132         shipp = getshipp(n);
133         sectp = getsectid(n);
134         landp = getlandp(n);
135         planep = getplanep(n);
136         do_upd_checking = 0;
137         if (shipp)
138             shp_do_upd_mob(shipp);
139         if (sectp)
140             sct_do_upd_mob(sectp);
141         if (landp)
142             lnd_do_upd_mob(landp);
143         if (planep)
144             pln_do_upd_mob(planep);
145         if (!shipp && !sectp && !landp && !planep)
146             break;
147         n++;
148     }
149     do_upd_checking = 0;
150 }
151
152 void
153 sct_do_upd_mob(register struct sctstr *sp)
154 {
155     extern float sect_mob_scale;
156     int etus;
157
158     if (do_upd_checking || timestamp_fixing || update_pending)
159         return;
160     if (sp->sct_own == 0)
161         return;
162     if (sp->sct_type == SCT_SANCT)
163         return;
164     if ((etus = increase_mob(&sp->sct_access, sect_mob_scale)) == 0)
165         return;
166     do_upd_checking = 1;
167     do_mob_sect(sp, etus);
168 /*    putsect(sp);*/
169     do_upd_checking = 0;
170 }
171
172 void
173 shp_do_upd_mob(register struct shpstr *sp)
174 {
175     extern float ship_mob_scale;
176     int etus;
177
178     if (do_upd_checking || timestamp_fixing || update_pending)
179         return;
180     if (sp->shp_own == 0)
181         return;
182     if ((etus = increase_mob(&sp->shp_access, ship_mob_scale)) == 0)
183         return;
184     do_upd_checking = 1;
185     do_mob_ship(sp, etus);
186     do_upd_checking = 0;
187 }
188
189 void
190 lnd_do_upd_mob(register struct lndstr *lp)
191 {
192     extern float land_mob_scale;
193     int etus;
194
195     if (do_upd_checking || timestamp_fixing || update_pending)
196         return;
197     if (lp->lnd_own == 0)
198         return;
199     if ((etus = increase_mob(&lp->lnd_access, land_mob_scale)) == 0)
200         return;
201
202     do_upd_checking = 1;
203     do_mob_land(lp, etus);
204     do_upd_checking = 0;
205 }
206
207 void
208 pln_do_upd_mob(register struct plnstr *pp)
209 {
210     extern float plane_mob_scale;
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(register int etus)
227 {
228     register struct sctstr *sp;
229     register 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 void
243 do_mob_sect(register struct sctstr *sp, register int etus)
244 {
245     extern float sect_mob_scale;
246     extern int sect_mob_max;
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 void
283 do_mob_ship(register struct shpstr *sp, register int etus)
284 {
285     extern int ship_mob_max;
286     extern float ship_mob_scale;
287     int newfuel = 0;
288     register int value;
289     int can_add, have_fuel_for, total_add;
290     double d;
291     extern int fuel_mult;
292
293     if (sp->shp_own == 0)
294         return;
295
296     /* Do we even have to bother updating this mobility? */
297     if (sp->shp_mobil >= ship_mob_max) {
298         /* No, so don't.  Just set it to max (just in case) and
299            return. */
300         sp->shp_mobil = ship_mob_max;
301         return;
302     }
303
304     if (opt_FUEL == 0) {        /* only a bit to do ... */
305         value = sp->shp_mobil + ((float)etus * ship_mob_scale);
306         if (value > ship_mob_max)
307             value = ship_mob_max;
308         sp->shp_mobil = value;
309         return;                 /* so we ship the FUEL stuff */
310     }
311
312     /* opt_FUEL in force */
313     if (mchr[(int)sp->shp_type].m_fuelu == 0) {
314         value = sp->shp_mobil + ((float)etus * ship_mob_scale);
315         if (value > ship_mob_max)
316             value = ship_mob_max;
317         sp->shp_mobil = (s_char)value;
318     } else {
319         can_add = ship_mob_max - sp->shp_mobil;
320         if (can_add > ((float)etus * ship_mob_scale))
321             can_add = ((float)etus * ship_mob_scale);
322         have_fuel_for = ldround((((double)sp->shp_fuel /
323                                   (double)mchr[(int)sp->shp_type].
324                                   m_fuelu) * (double)fuel_mult), 1);
325
326         if (can_add > have_fuel_for) {
327             int need;
328             need = can_add - have_fuel_for;
329             d = (double)need;
330             d *= (double)mchr[(int)sp->shp_type].m_fuelu;
331             d /= (double)fuel_mult;
332             d /= 5.0;
333             if ((d - (int)d) > 0.0)
334                 d++;
335             need = (int)d;
336             newfuel = supply_commod(sp->shp_own, sp->shp_x,
337                                     sp->shp_y, I_PETROL, need);
338             sp->shp_fuel += (u_char)(newfuel * 5);
339         }
340
341         have_fuel_for = ldround((((double)sp->shp_fuel /
342                                   (double)mchr[(int)sp->shp_type].
343                                   m_fuelu) * (double)fuel_mult), 1);
344
345         if (can_add > have_fuel_for) {
346             int need;
347             need = can_add - have_fuel_for;
348             d = (double)need;
349             d *= (double)mchr[(int)sp->shp_type].m_fuelu;
350             d /= (double)fuel_mult;
351             d /= 50.0;
352             if ((d - (int)d) > 0.0)
353                 d++;
354             need = (int)d;
355             newfuel = supply_commod(sp->shp_own, sp->shp_x,
356                                     sp->shp_y, I_OIL, need);
357             sp->shp_fuel += (u_char)(newfuel * 50);
358         }
359
360         have_fuel_for = ldround((((double)sp->shp_fuel /
361                                   (double)mchr[(int)sp->shp_type].
362                                   m_fuelu) * (double)fuel_mult), 1);
363
364         if (can_add > have_fuel_for)
365             total_add = have_fuel_for;
366         else
367             total_add = can_add;
368         d = (double)total_add;
369         d *= (double)mchr[(int)sp->shp_type].m_fuelu;
370         d /= (double)fuel_mult;
371         sp->shp_fuel -= (u_char)ldround(d, 1);
372         sp->shp_fuel = (u_char)min(sp->shp_fuel,
373                                    mchr[(int)sp->shp_type].m_fuelc);
374         sp->shp_mobil += (s_char)total_add;
375     }
376 }
377
378 void
379 mob_land(register int etus)
380 {
381     register struct lndstr *lp;
382     register int n;
383     time_t now;
384
385     time(&now);
386     for (n = 0; NULL != (lp = getlandp(n)); n++) {
387         lp->lnd_timestamp = now;
388         if (opt_MOB_ACCESS)
389             lnd_do_upd_mob(lp);
390         else
391             do_mob_land(lp, etus);
392     }
393 }
394
395 void
396 do_mob_land(register struct lndstr *lp, register int etus)
397 {
398     extern int land_mob_max;
399     extern float land_mob_scale;
400     int newfuel = 0;
401     register int value;
402     int can_add, have_fuel_for, total_add;
403     double d;
404     extern int fuel_mult;
405
406     if (lp->lnd_own == 0)
407         return;
408
409     if (lp->lnd_mobil >= land_mob_max) {
410         lp->lnd_mobil = land_mob_max;
411         return;
412     }
413
414     /*
415      * Give damaged units a break. When at low
416      * efficiency, units can go to -100 mob when
417      * marching 1 step, making them slower than
418      * normal mil. This helps take the curse off.
419      * If MOB_ACCESS is on, we don't do this, as it would
420      * be too much of an advantage.  So, we just add double
421      * the small amount of mob if we are < 0 instead.
422      */
423
424     if (!opt_MOB_ACCESS) {
425         if (lp->lnd_mobil < 0)
426             lp->lnd_mobil /= 2;
427     }
428
429     if (opt_FUEL == 0) {        /* just some bits and pieces */
430         if (opt_MOB_ACCESS) {
431             if (lp->lnd_mobil < 0)
432                 value =
433                     lp->lnd_mobil + (2 * ((float)etus * land_mob_scale));
434             else
435                 value = lp->lnd_mobil + ((float)etus * land_mob_scale);
436         } else {
437             value = lp->lnd_mobil + ((float)etus * land_mob_scale);
438         }
439         if (value > land_mob_max)
440             value = land_mob_max;
441         lp->lnd_mobil = value;
442
443         return;                 /* Done! */
444     }
445
446     /* opt_FUEL in force ... */
447     if (lp->lnd_fuelu == 0) {
448         if (opt_MOB_ACCESS) {
449             if (lp->lnd_mobil < 0)
450                 value =
451                     lp->lnd_mobil + (2 * ((float)etus * land_mob_scale));
452             else
453                 value = lp->lnd_mobil + ((float)etus * land_mob_scale);
454         } else {
455             value = lp->lnd_mobil + ((float)etus * land_mob_scale);
456         }
457         if (value > land_mob_max)
458             value = land_mob_max;
459         lp->lnd_mobil = value;
460
461     } else {
462
463         can_add = land_mob_max - lp->lnd_mobil;
464
465         if (can_add > ((float)etus * land_mob_scale))
466             can_add = ((float)etus * land_mob_scale);
467
468         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
469
470         if (can_add > have_fuel_for) {
471             int need;
472             need = can_add - have_fuel_for;
473             d = (double)need;
474             d *= (double)lp->lnd_fuelu;
475             d /= (double)fuel_mult;
476             d /= 5.0;
477             if ((d - (int)d) > 0.0)
478                 d++;
479             need = (int)d;
480             newfuel = supply_commod(lp->lnd_own, lp->lnd_x,
481                                     lp->lnd_y, I_PETROL, need);
482             lp->lnd_fuel += (u_char)(newfuel * 5);
483         }
484
485         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
486
487         if (can_add > have_fuel_for) {
488             int need;
489             need = can_add - have_fuel_for;
490             d = (double)need;
491             d *= (double)lp->lnd_fuelu;
492             d /= (double)fuel_mult;
493             d /= 50.0;
494             if ((d - (int)d) > 0.0)
495                 d++;
496             need = (int)d;
497             newfuel = supply_commod(lp->lnd_own, lp->lnd_x,
498                                     lp->lnd_y, I_OIL, need);
499             lp->lnd_fuel += (u_char)(newfuel * 50);
500         }
501
502         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
503
504         if (can_add > have_fuel_for) {
505             total_add = have_fuel_for;
506         } else
507             total_add = can_add;
508         d = (double)total_add;
509         d *= (double)lp->lnd_fuelu;
510         d /= (double)fuel_mult;
511         lp->lnd_fuel -= (u_char)ldround(d, 1);
512         lp->lnd_fuel = (u_char)min(lp->lnd_fuel, lp->lnd_fuelc);
513         if (total_add + lp->lnd_mobil > land_mob_max) {
514             total_add = land_mob_max - lp->lnd_mobil;
515         }
516
517         if (opt_MOB_ACCESS) {
518             if (lp->lnd_mobil < 0)
519                 lp->lnd_mobil += (s_char)total_add;
520         }
521         lp->lnd_mobil += (s_char)total_add;
522     }
523 }
524
525 void
526 mob_plane(register int etus)
527 {
528     register struct plnstr *pp;
529     register int n;
530     time_t now;
531
532     time(&now);
533     for (n = 0; NULL != (pp = getplanep(n)); n++) {
534         pp->pln_timestamp = now;
535         if (opt_MOB_ACCESS)
536             pln_do_upd_mob(pp);
537         else
538             do_mob_plane(pp, etus);
539     }
540 }
541
542 void
543 do_mob_plane(register struct plnstr *pp, register int etus)
544 {
545     extern int plane_mob_max;
546     extern float plane_mob_scale;
547     register int value;
548
549     if (pp->pln_own == 0)
550         return;
551     if (pp->pln_mobil >= plane_mob_max) {
552         pp->pln_mobil = plane_mob_max;
553         return;
554     }
555
556     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
557     if (value > plane_mob_max)
558         value = plane_mob_max;
559     pp->pln_mobil = value;
560 }