]> git.pond.sub.org Git - empserver/blob - src/lib/update/mobility.c
Import of Empire 4.2.12
[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].m_fuelu)*
324                                  (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].m_fuelu)*
343                                  (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].m_fuelu)*
362                                  (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 = lp->lnd_mobil + (2 * ((float)etus * land_mob_scale));
433         else
434             value = lp->lnd_mobil + ((float)etus * land_mob_scale);
435       } else {
436         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
437       }
438       if (value > land_mob_max)
439         value = land_mob_max;
440       lp->lnd_mobil = value;
441
442       return; /* Done! */
443     }
444     
445     /* opt_FUEL in force ... */
446     if (lp->lnd_fuelu == 0){
447       if (opt_MOB_ACCESS) {
448         if (lp->lnd_mobil < 0)
449             value = lp->lnd_mobil + (2 * ((float)etus * land_mob_scale));
450         else
451             value = lp->lnd_mobil + ((float)etus * land_mob_scale);
452       } else {
453         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
454       }
455       if (value > land_mob_max)
456         value = land_mob_max;
457       lp->lnd_mobil = value;
458
459     } else {
460         
461       can_add = land_mob_max - lp->lnd_mobil;      
462         
463         if (can_add > ((float)etus*land_mob_scale))
464             can_add = ((float)etus*land_mob_scale);
465
466         have_fuel_for = (lp->lnd_fuel /
467                          lp->lnd_fuelu)*fuel_mult;
468
469         if (can_add > have_fuel_for){
470             int     need;
471             need = can_add - have_fuel_for;
472             d = (double)need;
473             d *= (double)lp->lnd_fuelu;
474             d /= (double)fuel_mult;
475             d /= 5.0;
476             if ((d-(int)d) > 0.0)
477                 d++;
478             need = (int)d;
479             newfuel = supply_commod(lp->lnd_own,lp->lnd_x,
480                                     lp->lnd_y,I_PETROL,need);
481             lp->lnd_fuel += (u_char)(newfuel * 5);
482         }
483
484         have_fuel_for = (lp->lnd_fuel /
485                          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 /
503                          lp->lnd_fuelu)*fuel_mult;
504
505         if (can_add > have_fuel_for){
506             total_add = have_fuel_for;
507         }
508         else
509             total_add = can_add;
510         d = (double)total_add;
511         d *= (double)lp->lnd_fuelu;
512         d /= (double)fuel_mult;
513         lp->lnd_fuel -= (u_char)ldround(d,1);
514         lp->lnd_fuel = (u_char)min(lp->lnd_fuel,
515                            lp->lnd_fuelc);
516         if(total_add + lp->lnd_mobil > land_mob_max) {
517             total_add = land_mob_max - lp->lnd_mobil;
518         }
519         
520         if (opt_MOB_ACCESS) {
521           if (lp->lnd_mobil < 0)
522             lp->lnd_mobil += (s_char)total_add;
523         }
524         lp->lnd_mobil += (s_char)total_add;
525     }
526 }
527
528 void
529 mob_plane(register int etus)
530 {
531         register struct plnstr *pp;
532         register int n;
533         time_t now;
534         
535         time(&now);
536         for (n=0; NULL != (pp = getplanep(n)); n++) {
537             pp->pln_timestamp = now;
538             if (opt_MOB_ACCESS)
539                         pln_do_upd_mob(pp);
540             else
541                         do_mob_plane(pp, etus);
542         }
543 }
544
545 void
546 do_mob_plane(register struct plnstr *pp, register int etus)
547 {
548     extern  int plane_mob_max;
549     extern  float plane_mob_scale;
550     register int value;
551
552     if (pp->pln_own == 0)
553         return;
554         if (pp->pln_mobil >= plane_mob_max) {
555                 pp->pln_mobil = plane_mob_max;
556                 return;
557         }
558
559     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
560     if (value > plane_mob_max)
561         value = plane_mob_max;
562     pp->pln_mobil = value;
563 }