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