]> git.pond.sub.org Git - empserver/blob - src/lib/update/mobility.c
Update known contributors comments
[empserver] / src / lib / update / mobility.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2008, 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  *     Markus Armbruster, 2004-2008
34  */
35
36 #include <config.h>
37
38 #include "game.h"
39 #include "land.h"
40 #include "plane.h"
41 #include "server.h"
42 #include "ship.h"
43 #include "update.h"
44
45 static int do_upd_checking;
46
47 static void do_mob_land(struct lndstr *, int);
48 static void do_mob_plane(struct plnstr *, int);
49 static void do_mob_sect(struct sctstr *sp, int etus);
50 static void do_mob_ship(struct shpstr *, int);
51
52 void
53 sct_do_upd_mob(struct sctstr *sp)
54 {
55     int etus;
56
57     if (do_upd_checking || update_running)
58         return;
59     if (sp->sct_own == 0)
60         return;
61     if (sp->sct_type == SCT_SANCT)
62         return;
63     etus = game_tick_to_now(&sp->sct_access);
64     if (etus == 0)
65         return;
66
67     do_upd_checking = 1;        /* avoid recursion */
68     do_mob_sect(sp, etus);
69     do_upd_checking = 0;
70 }
71
72 void
73 shp_do_upd_mob(struct shpstr *sp)
74 {
75     int etus;
76
77     if (do_upd_checking || update_running)
78         return;
79     if (sp->shp_own == 0)
80         return;
81     etus = game_tick_to_now(&sp->shp_access);
82     if (etus == 0)
83         return;
84
85     do_upd_checking = 1;        /* avoid recursion */
86     do_mob_ship(sp, etus);
87     do_upd_checking = 0;
88 }
89
90 void
91 lnd_do_upd_mob(struct lndstr *lp)
92 {
93     int etus;
94
95     if (do_upd_checking || update_running)
96         return;
97     if (lp->lnd_own == 0)
98         return;
99     etus = game_tick_to_now(&lp->lnd_access);
100     if (etus == 0)
101         return;
102
103     do_upd_checking = 1;        /* avoid recursion */
104     do_mob_land(lp, etus);
105     do_upd_checking = 0;
106 }
107
108 void
109 pln_do_upd_mob(struct plnstr *pp)
110 {
111     int etus;
112
113     if (do_upd_checking || update_running)
114         return;
115     if (pp->pln_own == 0)
116         return;
117     etus = game_tick_to_now(&pp->pln_access);
118     if (etus == 0)
119         return;
120
121     do_upd_checking = 1;        /* avoid recursion */
122     do_mob_plane(pp, etus);
123     do_upd_checking = 0;
124 }
125
126 void
127 mob_sect(void)
128 {
129     struct sctstr *sp;
130     int n, etus;
131     time_t now;
132
133     time(&now);
134     for (n = 0; NULL != (sp = getsectid(n)); n++) {
135         sp->sct_timestamp = now;
136         if (opt_MOB_ACCESS)
137             etus = game_reset_tick(&sp->sct_access);
138         else
139             etus = etu_per_update;
140         do_mob_sect(sp, etus);
141     }
142 }
143
144 static void
145 do_mob_sect(struct sctstr *sp, int etus)
146 {
147     int value;
148
149     if (CANT_HAPPEN(etus < 0))
150         etus = 0;
151
152     if (sp->sct_own == 0)
153         return;
154     if (sp->sct_type == SCT_SANCT)
155         return;
156
157     value = sp->sct_mobil + ((float)etus * sect_mob_scale);
158     if (value > sect_mob_max)
159         value = sect_mob_max;
160     sp->sct_mobil = value;
161 }
162
163 void
164 mob_ship(void)
165 {
166     struct shpstr *sp;
167     int n, etus;
168     time_t now;
169
170     time(&now);
171     for (n = 0; NULL != (sp = getshipp(n)); n++) {
172         sp->shp_timestamp = now;
173         if (opt_MOB_ACCESS)
174             etus = game_reset_tick(&sp->shp_access);
175         else
176             etus = etu_per_update;
177         do_mob_ship(sp, etus);
178     }
179 }
180
181 static void
182 do_mob_ship(struct shpstr *sp, int etus)
183 {
184     int newfuel = 0;
185     int value;
186     int can_add, have_fuel_for, total_add;
187     double d;
188
189     if (CANT_HAPPEN(etus < 0))
190         etus = 0;
191
192     if (sp->shp_own == 0)
193         return;
194
195     if (opt_FUEL == 0 || mchr[(int)sp->shp_type].m_fuelu == 0) {
196         value = sp->shp_mobil + (float)etus * ship_mob_scale;
197         if (value > ship_mob_max)
198             value = ship_mob_max;
199         sp->shp_mobil = (signed char)value;
200     } else {
201         if (sp->shp_mobil >= ship_mob_max) {
202             sp->shp_mobil = ship_mob_max;
203             return;
204         }
205         can_add = ship_mob_max - sp->shp_mobil;
206         if (can_add > (float)etus * ship_mob_scale)
207             can_add = (float)etus * ship_mob_scale;
208         have_fuel_for = ldround(((double)sp->shp_fuel /
209                                  (double)mchr[(int)sp->shp_type].m_fuelu)
210                                 * (double)fuel_mult, 1);
211
212         if (can_add > have_fuel_for) {
213             int need;
214             need = can_add - have_fuel_for;
215             d = need;
216             d *= mchr[(int)sp->shp_type].m_fuelu;
217             d /= fuel_mult;
218             d /= 5.0;
219             if (d - (int)d > 0.0)
220                 d++;
221             need = (int)d;
222             newfuel = supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
223                                     I_PETROL, need);
224             sp->shp_fuel += newfuel * 5;
225         }
226
227         have_fuel_for = ldround(((double)sp->shp_fuel /
228                                  (double)mchr[(int)sp->shp_type].m_fuelu)
229                                 * (double)fuel_mult, 1);
230
231         if (can_add > have_fuel_for) {
232             int need;
233             need = can_add - have_fuel_for;
234             d = need;
235             d *= mchr[(int)sp->shp_type].m_fuelu;
236             d /= fuel_mult;
237             d /= 50.0;
238             if (d - (int)d > 0.0)
239                 d++;
240             need = (int)d;
241             newfuel = supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
242                                     I_OIL, need);
243             sp->shp_fuel += newfuel * 50;
244         }
245
246         have_fuel_for = ldround(((double)sp->shp_fuel /
247                                  (double)mchr[(int)sp->shp_type].m_fuelu)
248                                 * (double)fuel_mult, 1);
249
250         if (can_add > have_fuel_for)
251             total_add = have_fuel_for;
252         else
253             total_add = can_add;
254         d = total_add;
255         d *= mchr[(int)sp->shp_type].m_fuelu;
256         d /= fuel_mult;
257         sp->shp_fuel -= ldround(d, 1);
258         sp->shp_fuel = MIN(sp->shp_fuel, mchr[(int)sp->shp_type].m_fuelc);
259         sp->shp_mobil += total_add;
260     }
261 }
262
263 void
264 mob_land(void)
265 {
266     struct lndstr *lp;
267     int n, etus;
268     time_t now;
269
270     time(&now);
271     for (n = 0; NULL != (lp = getlandp(n)); n++) {
272         lp->lnd_timestamp = now;
273         if (opt_MOB_ACCESS)
274             etus = game_reset_tick(&lp->lnd_access);
275         else
276             etus = etu_per_update;
277         do_mob_land(lp, etus);
278     }
279 }
280
281 static void
282 do_mob_land(struct lndstr *lp, int etus)
283 {
284     int newfuel = 0;
285     int value;
286     int can_add, have_fuel_for, total_add;
287     double d;
288     struct lchrstr *lcp = lchr + lp->lnd_type;
289
290     if (CANT_HAPPEN(etus < 0))
291         etus = 0;
292
293     if (lp->lnd_own == 0)
294         return;
295
296     if (opt_FUEL == 0 || lcp->l_fuelu == 0) {
297         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
298         if (value > land_mob_max) {
299             if (lp->lnd_harden < land_mob_max && !opt_MOB_ACCESS) {
300                 /*
301                  * Automatic fortification on excess mobility.
302                  * Disabled for MOB_ACCESS, because it leads to
303                  * excessively deep recursion and thus miserable
304                  * performance as the number of land units grows.
305                  *
306                  * Provide mobility to be used in lnd_fortify()
307                  * without overflowing lnd_mobil.
308                  */
309                 lp->lnd_mobil = land_mob_max;
310                 lnd_fortify(lp, value - land_mob_max);
311             }
312             value = land_mob_max;
313         }
314         lp->lnd_mobil = value;
315
316     } else {
317         if (lp->lnd_mobil >= land_mob_max) {
318             lp->lnd_mobil = land_mob_max;
319             return;
320         }
321
322         can_add = land_mob_max - lp->lnd_mobil;
323
324         if (can_add > (float)etus * land_mob_scale)
325             can_add = (float)etus * land_mob_scale;
326
327         have_fuel_for = (lp->lnd_fuel / lcp->l_fuelu) * fuel_mult;
328
329         if (can_add > have_fuel_for) {
330             int need;
331             need = can_add - have_fuel_for;
332             d = need;
333             d *= lcp->l_fuelu;
334             d /= fuel_mult;
335             d /= 5.0;
336             if (d - (int)d > 0.0)
337                 d++;
338             need = (int)d;
339             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
340                                     I_PETROL, need);
341             lp->lnd_fuel += newfuel * 5;
342         }
343
344         have_fuel_for = (lp->lnd_fuel / lcp->l_fuelu) * fuel_mult;
345
346         if (can_add > have_fuel_for) {
347             int need;
348             need = can_add - have_fuel_for;
349             d = need;
350             d *= lcp->l_fuelu;
351             d /= fuel_mult;
352             d /= 50.0;
353             if (d - (int)d > 0.0)
354                 d++;
355             need = (int)d;
356             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
357                                     I_OIL, need);
358             lp->lnd_fuel += newfuel * 50;
359         }
360
361         have_fuel_for = (lp->lnd_fuel / lcp->l_fuelu) * fuel_mult;
362
363         if (can_add > have_fuel_for) {
364             total_add = have_fuel_for;
365         } else
366             total_add = can_add;
367         d = total_add;
368         d *= lcp->l_fuelu;
369         d /= fuel_mult;
370         lp->lnd_fuel -= ldround(d, 1);
371         lp->lnd_fuel = MIN(lp->lnd_fuel, lcp->l_fuelc);
372         lp->lnd_mobil += total_add;
373         /* No excess mobility here, hence no automatic fortification */
374     }
375 }
376
377 void
378 mob_plane(void)
379 {
380     struct plnstr *pp;
381     int n, etus;
382     time_t now;
383
384     time(&now);
385     for (n = 0; NULL != (pp = getplanep(n)); n++) {
386         pp->pln_timestamp = now;
387         if (opt_MOB_ACCESS)
388             etus = game_reset_tick(&pp->pln_access);
389         else
390             etus = etu_per_update;
391         do_mob_plane(pp, etus);
392     }
393 }
394
395 static void
396 do_mob_plane(struct plnstr *pp, int etus)
397 {
398     int value;
399
400     if (CANT_HAPPEN(etus < 0))
401         etus = 0;
402
403     if (pp->pln_own == 0)
404         return;
405
406     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
407     if (value > plane_mob_max)
408         value = plane_mob_max;
409     pp->pln_mobil = value;
410 }