]> git.pond.sub.org Git - empserver/blob - src/lib/update/mobility.c
Break lines more tastefully.
[empserver] / src / lib / update / mobility.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2006, 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 files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future 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 <config.h>
36
37 #include "misc.h"
38 #include "sect.h"
39 #include "ship.h"
40 #include "land.h"
41 #include "plane.h"
42 #include "nat.h"
43 #include "file.h"
44 #include "optlist.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(struct lndstr *, int);
58 static void do_mob_plane(struct plnstr *, int);
59 static void do_mob_sect(struct sctstr *sp, int etus);
60 static void do_mob_ship(struct shpstr *, 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 = newetus * mult;
83         inewmob = (int)newmob;
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     *counter = now - 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 = (signed 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].m_fuelu)
319                                  * (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, sp->shp_y,
332                                     I_PETROL, need);
333             sp->shp_fuel += newfuel * 5;
334         }
335
336         have_fuel_for = ldround((((double)sp->shp_fuel /
337                                   (double)mchr[(int)sp->shp_type].m_fuelu)
338                                  * (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, sp->shp_y,
351                                     I_OIL, need);
352             sp->shp_fuel += newfuel * 50;
353         }
354
355         have_fuel_for = ldround((((double)sp->shp_fuel /
356                                   (double)mchr[(int)sp->shp_type].m_fuelu)
357                                  * (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 -= ldround(d, 1);
367         sp->shp_fuel = MIN(sp->shp_fuel, mchr[(int)sp->shp_type].m_fuelc);
368         sp->shp_mobil += total_add;
369     }
370 }
371
372 void
373 mob_land(int etus)
374 {
375     struct lndstr *lp;
376     int n;
377     time_t now;
378
379     time(&now);
380     for (n = 0; NULL != (lp = getlandp(n)); n++) {
381         lp->lnd_timestamp = now;
382         if (opt_MOB_ACCESS)
383             lnd_do_upd_mob(lp);
384         else
385             do_mob_land(lp, etus);
386     }
387 }
388
389 static void
390 do_mob_land(struct lndstr *lp, int etus)
391 {
392     int newfuel = 0;
393     int value;
394     int can_add, have_fuel_for, total_add;
395     double d;
396
397     if (lp->lnd_own == 0)
398         return;
399
400     if (lp->lnd_mobil >= land_mob_max) {
401         lp->lnd_mobil = land_mob_max;
402         if (lp->lnd_harden >= land_mob_max) {
403             lp->lnd_harden = land_mob_max;
404             return;
405         }
406     }
407
408     if (opt_FUEL == 0) {        /* just some bits and pieces */
409         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
410         if (value > land_mob_max) {
411             lnd_fortify(lp, value - land_mob_max);
412             value = land_mob_max;
413         }
414         lp->lnd_mobil = value;
415
416         return;                 /* Done! */
417     }
418
419     /* opt_FUEL in force ... */
420     if (lp->lnd_fuelu == 0) {
421         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
422         if (value > land_mob_max) {
423             lnd_fortify(lp, value - land_mob_max);
424             value = land_mob_max;
425         }
426         lp->lnd_mobil = value;
427
428     } else {
429
430         can_add = land_mob_max - lp->lnd_mobil;
431
432         if (can_add > ((float)etus * land_mob_scale))
433             can_add = ((float)etus * land_mob_scale);
434
435         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
436
437         if (can_add > have_fuel_for) {
438             int need;
439             need = can_add - have_fuel_for;
440             d = (double)need;
441             d *= (double)lp->lnd_fuelu;
442             d /= (double)fuel_mult;
443             d /= 5.0;
444             if ((d - (int)d) > 0.0)
445                 d++;
446             need = (int)d;
447             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
448                                     I_PETROL, need);
449             lp->lnd_fuel += newfuel * 5;
450         }
451
452         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
453
454         if (can_add > have_fuel_for) {
455             int need;
456             need = can_add - have_fuel_for;
457             d = (double)need;
458             d *= (double)lp->lnd_fuelu;
459             d /= (double)fuel_mult;
460             d /= 50.0;
461             if ((d - (int)d) > 0.0)
462                 d++;
463             need = (int)d;
464             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
465                                     I_OIL, need);
466             lp->lnd_fuel += newfuel * 50;
467         }
468
469         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
470
471         if (can_add > have_fuel_for) {
472             total_add = have_fuel_for;
473         } else
474             total_add = can_add;
475         d = (double)total_add;
476         d *= (double)lp->lnd_fuelu;
477         d /= (double)fuel_mult;
478         lp->lnd_fuel -= ldround(d, 1);
479         lp->lnd_fuel = MIN(lp->lnd_fuel, lp->lnd_fuelc);
480         lp->lnd_mobil += total_add;
481         /* No excess mobility here, hence no automatic fortification */
482     }
483 }
484
485 void
486 mob_plane(int etus)
487 {
488     struct plnstr *pp;
489     int n;
490     time_t now;
491
492     time(&now);
493     for (n = 0; NULL != (pp = getplanep(n)); n++) {
494         pp->pln_timestamp = now;
495         if (opt_MOB_ACCESS)
496             pln_do_upd_mob(pp);
497         else
498             do_mob_plane(pp, etus);
499     }
500 }
501
502 static void
503 do_mob_plane(struct plnstr *pp, int etus)
504 {
505     int value;
506
507     if (pp->pln_own == 0)
508         return;
509     if (pp->pln_mobil >= plane_mob_max) {
510         pp->pln_mobil = plane_mob_max;
511         return;
512     }
513
514     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
515     if (value > plane_mob_max)
516         value = plane_mob_max;
517     pp->pln_mobil = value;
518 }