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