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