]> git.pond.sub.org Git - empserver/blob - src/lib/update/mobility.c
(do_mob_land): Do not regenerate mobility faster while it is negative.
[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 static void do_mob_land(register struct lndstr *, register int);
55 static void do_mob_plane(register struct plnstr *, register int);
56 static void do_mob_sect(register struct sctstr *sp, register int etus);
57 static void do_mob_ship(register struct shpstr *, register int);
58
59 int
60 increase_mob(time_t * counter, float mult)
61 {
62     time_t secs;
63     time_t now;
64     time_t left;
65     extern long s_p_etu;
66     extern int updating_mob;
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(register struct sctstr *sp)
158 {
159     extern float sect_mob_scale;
160     int etus;
161
162     if (do_upd_checking || timestamp_fixing || update_pending)
163         return;
164     if (sp->sct_own == 0)
165         return;
166     if (sp->sct_type == SCT_SANCT)
167         return;
168     if ((etus = increase_mob(&sp->sct_access, sect_mob_scale)) == 0)
169         return;
170     do_upd_checking = 1;
171     do_mob_sect(sp, etus);
172 /*    putsect(sp);*/
173     do_upd_checking = 0;
174 }
175
176 void
177 shp_do_upd_mob(register struct shpstr *sp)
178 {
179     extern float ship_mob_scale;
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     extern float land_mob_scale;
197     int etus;
198
199     if (do_upd_checking || timestamp_fixing || update_pending)
200         return;
201     if (lp->lnd_own == 0)
202         return;
203     if ((etus = increase_mob(&lp->lnd_access, land_mob_scale)) == 0)
204         return;
205
206     do_upd_checking = 1;
207     do_mob_land(lp, etus);
208     do_upd_checking = 0;
209 }
210
211 void
212 pln_do_upd_mob(register struct plnstr *pp)
213 {
214     extern float plane_mob_scale;
215     int etus;
216
217     if (do_upd_checking || timestamp_fixing || update_pending)
218         return;
219     if (pp->pln_own == 0)
220         return;
221     if ((etus = increase_mob(&pp->pln_access, plane_mob_scale)) == 0)
222         return;
223
224     do_upd_checking = 1;
225     do_mob_plane(pp, etus);
226     do_upd_checking = 0;
227 }
228
229 void
230 mob_sect(register int etus)
231 {
232     register struct sctstr *sp;
233     register int n;
234     time_t now;
235
236     time(&now);
237     for (n = 0; NULL != (sp = getsectid(n)); n++) {
238         sp->sct_timestamp = now;
239         if (opt_MOB_ACCESS)
240             sct_do_upd_mob(sp);
241         else
242             do_mob_sect(sp, etus);
243     }
244 }
245
246 static void
247 do_mob_sect(register struct sctstr *sp, register int etus)
248 {
249     extern float sect_mob_scale;
250     extern int sect_mob_max;
251     register int value;
252
253     if (sp->sct_own == 0)
254         return;
255     if (sp->sct_type == SCT_SANCT)
256         return;
257     /* Do we have to even bother? */
258     if (sp->sct_mobil >= sect_mob_max) {
259         /* No, so set just in case and then return */
260         sp->sct_mobil = sect_mob_max;
261         return;
262     }
263     value = sp->sct_mobil + ((float)etus * sect_mob_scale);
264     if (value > sect_mob_max)
265         value = sect_mob_max;
266     sp->sct_mobil = value;
267 }
268
269 void
270 mob_ship(register int etus)
271 {
272     register struct shpstr *sp;
273     register int n;
274     time_t now;
275
276     time(&now);
277     for (n = 0; NULL != (sp = getshipp(n)); n++) {
278         sp->shp_timestamp = now;
279         if (opt_MOB_ACCESS)
280             shp_do_upd_mob(sp);
281         else
282             do_mob_ship(sp, etus);
283     }
284 }
285
286 static void
287 do_mob_ship(register struct shpstr *sp, register int etus)
288 {
289     extern int ship_mob_max;
290     extern float ship_mob_scale;
291     int newfuel = 0;
292     register int value;
293     int can_add, have_fuel_for, total_add;
294     double d;
295     extern int fuel_mult;
296
297     if (sp->shp_own == 0)
298         return;
299
300     /* Do we even have to bother updating this mobility? */
301     if (sp->shp_mobil >= ship_mob_max) {
302         /* No, so don't.  Just set it to max (just in case) and
303            return. */
304         sp->shp_mobil = ship_mob_max;
305         return;
306     }
307
308     if (opt_FUEL == 0) {        /* only a bit to do ... */
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 = value;
313         return;                 /* so we ship the FUEL stuff */
314     }
315
316     /* opt_FUEL in force */
317     if (mchr[(int)sp->shp_type].m_fuelu == 0) {
318         value = sp->shp_mobil + ((float)etus * ship_mob_scale);
319         if (value > ship_mob_max)
320             value = ship_mob_max;
321         sp->shp_mobil = (s_char)value;
322     } else {
323         can_add = ship_mob_max - sp->shp_mobil;
324         if (can_add > ((float)etus * ship_mob_scale))
325             can_add = ((float)etus * ship_mob_scale);
326         have_fuel_for = ldround((((double)sp->shp_fuel /
327                                   (double)mchr[(int)sp->shp_type].
328                                   m_fuelu) * (double)fuel_mult), 1);
329
330         if (can_add > have_fuel_for) {
331             int need;
332             need = can_add - have_fuel_for;
333             d = (double)need;
334             d *= (double)mchr[(int)sp->shp_type].m_fuelu;
335             d /= (double)fuel_mult;
336             d /= 5.0;
337             if ((d - (int)d) > 0.0)
338                 d++;
339             need = (int)d;
340             newfuel = supply_commod(sp->shp_own, sp->shp_x,
341                                     sp->shp_y, I_PETROL, need);
342             sp->shp_fuel += (u_char)(newfuel * 5);
343         }
344
345         have_fuel_for = ldround((((double)sp->shp_fuel /
346                                   (double)mchr[(int)sp->shp_type].
347                                   m_fuelu) * (double)fuel_mult), 1);
348
349         if (can_add > have_fuel_for) {
350             int need;
351             need = can_add - have_fuel_for;
352             d = (double)need;
353             d *= (double)mchr[(int)sp->shp_type].m_fuelu;
354             d /= (double)fuel_mult;
355             d /= 50.0;
356             if ((d - (int)d) > 0.0)
357                 d++;
358             need = (int)d;
359             newfuel = supply_commod(sp->shp_own, sp->shp_x,
360                                     sp->shp_y, I_OIL, need);
361             sp->shp_fuel += (u_char)(newfuel * 50);
362         }
363
364         have_fuel_for = ldround((((double)sp->shp_fuel /
365                                   (double)mchr[(int)sp->shp_type].
366                                   m_fuelu) * (double)fuel_mult), 1);
367
368         if (can_add > have_fuel_for)
369             total_add = have_fuel_for;
370         else
371             total_add = can_add;
372         d = (double)total_add;
373         d *= (double)mchr[(int)sp->shp_type].m_fuelu;
374         d /= (double)fuel_mult;
375         sp->shp_fuel -= (u_char)ldround(d, 1);
376         sp->shp_fuel = (u_char)min(sp->shp_fuel,
377                                    mchr[(int)sp->shp_type].m_fuelc);
378         sp->shp_mobil += (s_char)total_add;
379     }
380 }
381
382 void
383 mob_land(register int etus)
384 {
385     register struct lndstr *lp;
386     register int n;
387     time_t now;
388
389     time(&now);
390     for (n = 0; NULL != (lp = getlandp(n)); n++) {
391         lp->lnd_timestamp = now;
392         if (opt_MOB_ACCESS)
393             lnd_do_upd_mob(lp);
394         else
395             do_mob_land(lp, etus);
396     }
397 }
398
399 static void
400 do_mob_land(register struct lndstr *lp, register int etus)
401 {
402     extern int land_mob_max;
403     extern float land_mob_scale;
404     int newfuel = 0;
405     register int value;
406     int can_add, have_fuel_for, total_add;
407     double d;
408     extern int fuel_mult;
409
410     if (lp->lnd_own == 0)
411         return;
412
413     if (lp->lnd_mobil >= land_mob_max) {
414         lp->lnd_mobil = land_mob_max;
415         if (lp->lnd_harden >= land_mob_max) {
416             lp->lnd_harden = land_mob_max;
417             return;
418         }
419     }
420
421     if (opt_FUEL == 0) {        /* just some bits and pieces */
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         return;                 /* Done! */
430     }
431
432     /* opt_FUEL in force ... */
433     if (lp->lnd_fuelu == 0) {
434         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
435         if (value > land_mob_max) {
436             lnd_fortify(lp, value - land_mob_max);
437             value = land_mob_max;
438         }
439         lp->lnd_mobil = value;
440
441     } else {
442
443         can_add = land_mob_max - lp->lnd_mobil;
444
445         if (can_add > ((float)etus * land_mob_scale))
446             can_add = ((float)etus * land_mob_scale);
447
448         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
449
450         if (can_add > have_fuel_for) {
451             int need;
452             need = can_add - have_fuel_for;
453             d = (double)need;
454             d *= (double)lp->lnd_fuelu;
455             d /= (double)fuel_mult;
456             d /= 5.0;
457             if ((d - (int)d) > 0.0)
458                 d++;
459             need = (int)d;
460             newfuel = supply_commod(lp->lnd_own, lp->lnd_x,
461                                     lp->lnd_y, I_PETROL, need);
462             lp->lnd_fuel += (u_char)(newfuel * 5);
463         }
464
465         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
466
467         if (can_add > have_fuel_for) {
468             int need;
469             need = can_add - have_fuel_for;
470             d = (double)need;
471             d *= (double)lp->lnd_fuelu;
472             d /= (double)fuel_mult;
473             d /= 50.0;
474             if ((d - (int)d) > 0.0)
475                 d++;
476             need = (int)d;
477             newfuel = supply_commod(lp->lnd_own, lp->lnd_x,
478                                     lp->lnd_y, I_OIL, need);
479             lp->lnd_fuel += (u_char)(newfuel * 50);
480         }
481
482         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
483
484         if (can_add > have_fuel_for) {
485             total_add = have_fuel_for;
486         } else
487             total_add = can_add;
488         d = (double)total_add;
489         d *= (double)lp->lnd_fuelu;
490         d /= (double)fuel_mult;
491         lp->lnd_fuel -= (u_char)ldround(d, 1);
492         lp->lnd_fuel = (u_char)min(lp->lnd_fuel, lp->lnd_fuelc);
493         if (total_add + lp->lnd_mobil > land_mob_max) {
494             total_add = land_mob_max - lp->lnd_mobil;
495         }
496         /* no automatic fortification here, as it would cost fuel */
497
498         lp->lnd_mobil += (s_char)total_add;
499     }
500 }
501
502 void
503 mob_plane(register int etus)
504 {
505     register struct plnstr *pp;
506     register int n;
507     time_t now;
508
509     time(&now);
510     for (n = 0; NULL != (pp = getplanep(n)); n++) {
511         pp->pln_timestamp = now;
512         if (opt_MOB_ACCESS)
513             pln_do_upd_mob(pp);
514         else
515             do_mob_plane(pp, etus);
516     }
517 }
518
519 static void
520 do_mob_plane(register struct plnstr *pp, register int etus)
521 {
522     extern int plane_mob_max;
523     extern float plane_mob_scale;
524     register int value;
525
526     if (pp->pln_own == 0)
527         return;
528     if (pp->pln_mobil >= plane_mob_max) {
529         pp->pln_mobil = plane_mob_max;
530         return;
531     }
532
533     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
534     if (value > plane_mob_max)
535         value = plane_mob_max;
536     pp->pln_mobil = value;
537 }