]> 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-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-2007
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
289     if (CANT_HAPPEN(etus < 0))
290         etus = 0;
291
292     if (lp->lnd_own == 0)
293         return;
294
295     if (opt_FUEL == 0 || lp->lnd_fuelu == 0) {
296         value = lp->lnd_mobil + ((float)etus * land_mob_scale);
297         if (value > land_mob_max) {
298             if (lp->lnd_harden < land_mob_max && !opt_MOB_ACCESS) {
299                 /*
300                  * Automatic fortification on excess mobility.
301                  * Disabled for MOB_ACCESS, because it leads to
302                  * excessively deep recursion and thus miserable
303                  * performance as the number of land units grows.
304                  *
305                  * Provide mobility to be used in lnd_fortify()
306                  * without overflowing lnd_mobil.
307                  */
308                 lp->lnd_mobil = land_mob_max;
309                 lnd_fortify(lp, value - land_mob_max);
310             }
311             value = land_mob_max;
312         }
313         lp->lnd_mobil = value;
314
315     } else {
316         if (lp->lnd_mobil >= land_mob_max) {
317             lp->lnd_mobil = land_mob_max;
318             return;
319         }
320
321         can_add = land_mob_max - lp->lnd_mobil;
322
323         if (can_add > (float)etus * land_mob_scale)
324             can_add = (float)etus * land_mob_scale;
325
326         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
327
328         if (can_add > have_fuel_for) {
329             int need;
330             need = can_add - have_fuel_for;
331             d = need;
332             d *= lp->lnd_fuelu;
333             d /= fuel_mult;
334             d /= 5.0;
335             if (d - (int)d > 0.0)
336                 d++;
337             need = (int)d;
338             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
339                                     I_PETROL, need);
340             lp->lnd_fuel += newfuel * 5;
341         }
342
343         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
344
345         if (can_add > have_fuel_for) {
346             int need;
347             need = can_add - have_fuel_for;
348             d = need;
349             d *= lp->lnd_fuelu;
350             d /= fuel_mult;
351             d /= 50.0;
352             if (d - (int)d > 0.0)
353                 d++;
354             need = (int)d;
355             newfuel = supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
356                                     I_OIL, need);
357             lp->lnd_fuel += newfuel * 50;
358         }
359
360         have_fuel_for = (lp->lnd_fuel / lp->lnd_fuelu) * fuel_mult;
361
362         if (can_add > have_fuel_for) {
363             total_add = have_fuel_for;
364         } else
365             total_add = can_add;
366         d = total_add;
367         d *= lp->lnd_fuelu;
368         d /= fuel_mult;
369         lp->lnd_fuel -= ldround(d, 1);
370         lp->lnd_fuel = MIN(lp->lnd_fuel, lp->lnd_fuelc);
371         lp->lnd_mobil += total_add;
372         /* No excess mobility here, hence no automatic fortification */
373     }
374 }
375
376 void
377 mob_plane(void)
378 {
379     struct plnstr *pp;
380     int n, etus;
381     time_t now;
382
383     time(&now);
384     for (n = 0; NULL != (pp = getplanep(n)); n++) {
385         pp->pln_timestamp = now;
386         if (opt_MOB_ACCESS)
387             etus = game_reset_tick(&pp->pln_access);
388         else
389             etus = etu_per_update;
390         do_mob_plane(pp, etus);
391     }
392 }
393
394 static void
395 do_mob_plane(struct plnstr *pp, int etus)
396 {
397     int value;
398
399     if (CANT_HAPPEN(etus < 0))
400         etus = 0;
401
402     if (pp->pln_own == 0)
403         return;
404
405     value = pp->pln_mobil + ((float)etus * plane_mob_scale);
406     if (value > plane_mob_max)
407         value = plane_mob_max;
408     pp->pln_mobil = value;
409 }