]> git.pond.sub.org Git - empserver/blob - src/lib/commands/fuel.c
Indented with src/scripts/indent-emp.
[empserver] / src / lib / commands / fuel.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  *  fuel.c: fuel ships/land units
29  * 
30  *  Known contributors to this file:
31  *     
32  */
33
34 #include "misc.h"
35 #include "player.h"
36 #include "var.h"
37 #include "xy.h"
38 #include "ship.h"
39 #include "plane.h"
40 #include "land.h"
41 #include "nat.h"
42 #include "nsc.h"
43 #include "deity.h"
44 #include "file.h"
45 #include "sect.h"
46 #include "optlist.h"
47 #include "commands.h"
48
49
50 union item_u {
51     struct shpstr ship;
52     struct lndstr land;
53 };
54
55 int
56 fuel(void)
57 {
58     struct nstr_item ni;
59     union item_u item, item2;
60     int type;
61     struct mchrstr *mp;
62     struct lchrstr *lcp;
63     s_char *p;
64     int fueled;
65     int land_fuel, ship_fuel;
66     int oil_amt, pet_amt, fuel_amt, tot_fuel, max_amt;
67     int move_amt;
68     float extra;
69     struct sctstr sect;
70     struct natstr *natp;
71     int harbor, sector;
72     int fuelled_ship = -1;
73     struct nstr_item tender, ltender;
74     s_char prompt[128];
75     s_char buf[1024];
76
77     if (opt_FUEL == 0) {
78         pr("Option 'FUEL' not enabled\n");
79         return RET_SYN;
80     }
81     if ((p =
82          getstarg(player->argp[1], "Ship or land unit (s,l)? ", buf)) == 0)
83         return RET_SYN;
84     type = ef_byname(p);
85     if (type == EF_SECTOR)
86         type = EF_SHIP;
87     if (type != EF_SHIP && type != EF_LAND) {
88         pr("Ships or land units only! (s, l)\n");
89         return RET_SYN;
90     }
91     sprintf(prompt, "%s(s)? ", ef_nameof(type));
92     p = getstarg(player->argp[2], prompt, buf);
93     if (!snxtitem(&ni, type, p))
94         return RET_SYN;
95     if (isdigit(*p))
96         fuelled_ship = atoi(p);
97     p = getstarg(player->argp[3], "Amount: ", buf);
98     if (p == 0 || *p == 0)
99         return RET_SYN;
100     fuel_amt = atoi(p);
101     if (fuel_amt <= 0) {
102         pr("Fuel amount must be positive!\n");
103         return RET_FAIL;
104     }
105
106     ni.flags &= ~(EFF_OWNER);
107
108     while (nxtitem(&ni, (s_char *)&item)) {
109         fueled = 0;
110         if (type == EF_SHIP) {
111             if (item.ship.shp_own != player->cnum) {
112                 int rel;
113
114                 if (item.ship.shp_uid != fuelled_ship)
115                     continue;
116                 natp = getnatp(player->cnum);
117                 rel = getrel(natp, item.ship.shp_own);
118                 if (rel < FRIENDLY)
119                     continue;
120             }
121             if (!getsect(item.ship.shp_x, item.ship.shp_y, &sect))
122                 continue;
123             if (!item.ship.shp_own)
124                 continue;
125
126             if ((sect.sct_type != SCT_HARBR)
127                 && (sect.sct_type != SCT_WATER)
128                 && (sect.sct_type != SCT_BSPAN) && (!opt_BIG_CITY
129                                                     || sect.sct_type !=
130                                                     SCT_CAPIT)) {
131                 pr("Sector %s is not a harbor, bridge span, or sea.\n",
132                    xyas(item.ship.shp_x, item.ship.shp_y,
133                         item.ship.shp_own));
134                 continue;
135             }
136
137             mp = &mchr[(int)item.ship.shp_type];
138
139             harbor = 0;
140             if (sect.sct_type == SCT_HARBR
141                 || (opt_BIG_CITY && sect.sct_type == SCT_CAPIT)) {
142                 harbor = 1;
143                 oil_amt = getvar(V_OIL, (s_char *)&sect, EF_SECTOR);
144                 pet_amt = getvar(V_PETROL, (s_char *)&sect, EF_SECTOR);
145                 if ((oil_amt + pet_amt) == 0)
146                     harbor = 0;
147
148                 if (sect.sct_effic < 2) {
149                     pr("The harbor at %s is not 2%% efficient yet.\n",
150                        xyas(item.ship.shp_x,
151                             item.ship.shp_y, player->cnum));
152                     harbor = 0;
153                 }
154                 if ((sect.sct_own != player->cnum) && sect.sct_own)
155                     harbor = 0;
156             }
157
158             if ((mp->m_fuelu == 0) && (item.ship.shp_own == player->cnum)) {
159                 pr("%s does not use fuel!\n", prship(&item.ship));
160                 continue;
161             }
162
163             if (harbor) {
164                 ship_fuel = item.ship.shp_fuel;
165                 oil_amt = getvar(V_OIL, (s_char *)&sect, EF_SECTOR);
166                 pet_amt = getvar(V_PETROL, (s_char *)&sect, EF_SECTOR);
167                 max_amt = mp->m_fuelc - ship_fuel;
168
169                 if (max_amt == 0) {
170                     pr("%s already has a full fuel load.\n",
171                        prship(&item.ship));
172                     continue;
173                 }
174                 tot_fuel = (oil_amt * 50 + pet_amt * 5);
175                 if (tot_fuel == 0) {
176                     pr("No fuel in the harbor at %s!\n",
177                        xyas(sect.sct_x, sect.sct_y, player->cnum));
178                     continue;
179                 }
180                 move_amt = min(tot_fuel, fuel_amt);
181                 move_amt = min(move_amt, max_amt);
182
183                 if (move_amt == 0)
184                     continue;
185
186                 item.ship.shp_fuel += move_amt;
187
188                 fueled = 1;
189                 if ((pet_amt * 5) >= move_amt) {
190                     extra = ((float)move_amt / 5.0) - (move_amt / 5);
191                     if (extra > 0.0)
192                         putvar(V_PETROL,
193                                max((pet_amt - (move_amt / 5)) - 1, 0),
194                                (s_char *)&sect, EF_SECTOR);
195                     else
196                         putvar(V_PETROL,
197                                max((pet_amt - (move_amt / 5)), 0),
198                                (s_char *)&sect, EF_SECTOR);
199                 } else {
200                     putvar(V_PETROL, 0, (s_char *)&sect, EF_SECTOR);
201                     move_amt -= pet_amt * 5;
202                     extra = ((float)move_amt / 50.0) - (move_amt / 50);
203                     putvar(V_OIL, max(oil_amt - (move_amt / 50), 0),
204                            (s_char *)&sect, EF_SECTOR);
205                     if (extra > 0.0)
206                         putvar(V_OIL,
207                                max((oil_amt - (move_amt / 50)) - 1, 0),
208                                (s_char *)&sect, EF_SECTOR);
209                     else
210                         putvar(V_OIL,
211                                max((oil_amt - (move_amt / 50)), 0),
212                                (s_char *)&sect, EF_SECTOR);
213                 }
214
215                 /* load plague */
216                 if (getvar(V_PSTAGE, (s_char *)&sect, EF_SECTOR) ==
217                     PLG_INFECT && getvar(V_PSTAGE,
218                                          (s_char *)&item.ship,
219                                          EF_SHIP) == PLG_HEALTHY)
220                     putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&item.ship,
221                            EF_SHIP);
222
223                 putsect(&sect);
224                 putship(item.ship.shp_uid, &item.ship);
225             } else {            /* not in a harbor */
226                 if (!player->argp[4])
227                     pr("%s is not in a supplied, efficient harbor\n",
228                        prship(&item.ship));
229                 if (!snxtitem
230                     (&tender, EF_SHIP,
231                      getstarg(player->argp[4], "Oiler? ", buf)))
232                     continue;
233
234                 if (!check_ship_ok(&item.ship))
235                     continue;
236
237                 if (!nxtitem(&tender, (s_char *)&item2))
238                     continue;
239
240                 if (!(mchr[(int)item2.ship.shp_type].m_flags & M_OILER)) {
241                     pr("%s is not an oiler!\n", prship(&item2.ship));
242                     continue;
243                 }
244                 if (item2.ship.shp_own != player->cnum) {
245                     pr("You don't own that oiler!\n");
246                     continue;
247                 }
248
249                 if ((item2.ship.shp_x != item.ship.shp_x) ||
250                     (item2.ship.shp_y != item.ship.shp_y)) {
251                     pr("Not in the same sector!\n");
252                     continue;
253                 }
254                 ship_fuel = item.ship.shp_fuel;
255                 oil_amt = getvar(V_OIL, (s_char *)&item2.ship, EF_SHIP);
256                 pet_amt = getvar(V_PETROL, (s_char *)&item2.ship, EF_SHIP);
257                 max_amt = mp->m_fuelc - ship_fuel;
258
259                 if (max_amt == 0) {
260                     pr("%s already has a full fuel load.\n",
261                        prship(&item.ship));
262                     continue;
263                 }
264                 tot_fuel = oil_amt * 50 + pet_amt * 5;
265                 move_amt = min(tot_fuel, fuel_amt);
266                 move_amt = min(move_amt, max_amt);
267
268                 if (move_amt == 0)
269                     continue;
270
271                 item.ship.shp_fuel += move_amt;
272
273                 fueled = 1;
274                 if ((pet_amt * 5) >= move_amt) {
275                     extra = ((float)move_amt / 5.0) - (move_amt / 5);
276                     if (extra > 0.0)
277                         putvar(V_PETROL,
278                                max((pet_amt - (move_amt / 5)) - 1, 0),
279                                (s_char *)&item2.ship, EF_SHIP);
280                     else
281                         putvar(V_PETROL,
282                                max((pet_amt - (move_amt / 5)), 0),
283                                (s_char *)&item2.ship, EF_SHIP);
284                 } else {
285                     putvar(V_PETROL, 0, (s_char *)&item2.ship, EF_SHIP);
286                     move_amt -= pet_amt * 5;
287                     extra = ((float)move_amt / 50.0) - (move_amt / 50);
288                     putvar(V_OIL, max(oil_amt - (move_amt / 50), 0),
289                            (s_char *)&item2.ship, EF_SHIP);
290                     if (extra > 0.0)
291                         putvar(V_OIL,
292                                max((oil_amt - (move_amt / 50)) - 1, 0),
293                                (s_char *)&item2.ship, EF_SHIP);
294                     else
295                         putvar(V_OIL,
296                                max((oil_amt - (move_amt / 50)), 0),
297                                (s_char *)&item2.ship, EF_SHIP);
298                 }
299
300                 /* load plague */
301                 if (getvar(V_PSTAGE, (s_char *)&item2.ship, EF_SHIP) ==
302                     PLG_INFECT && getvar(V_PSTAGE,
303                                          (s_char *)&item.ship,
304                                          EF_SHIP) == PLG_HEALTHY)
305                     putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&item.ship,
306                            EF_SHIP);
307
308                 putship(item.ship.shp_uid, &item.ship);
309                 /* quick hack -KHS */
310                 if (item.ship.shp_uid == item2.ship.shp_uid)
311                     item2.ship.shp_fuel = item.ship.shp_fuel;
312                 putship(item2.ship.shp_uid, &item2.ship);
313             }
314             pr("%s", prship(&item.ship));
315         } else {
316             if (item.land.lnd_own != player->cnum)
317                 continue;
318
319             if (!getsect(item.land.lnd_x, item.land.lnd_y, &sect))
320                 continue;
321
322             if (!player->owner)
323                 continue;
324
325             lcp = &lchr[(int)item.land.lnd_type];
326
327             sector = 1;
328             oil_amt = getvar(V_OIL, (s_char *)&sect, EF_SECTOR);
329             pet_amt = getvar(V_PETROL, (s_char *)&sect, EF_SECTOR);
330
331             if ((oil_amt + pet_amt) == 0)
332                 sector = 0;
333
334             if ((item.land.lnd_fuelu == 0)
335                 && (item.land.lnd_own == player->cnum)) {
336                 pr("%s does not use fuel!\n", prland(&item.land));
337                 continue;
338             }
339
340             if (sector) {
341                 land_fuel = item.land.lnd_fuel;
342                 oil_amt = getvar(V_OIL, (s_char *)&sect, EF_SECTOR);
343                 pet_amt = getvar(V_PETROL, (s_char *)&sect, EF_SECTOR);
344                 max_amt = item.land.lnd_fuelc - land_fuel;
345
346                 if (max_amt == 0) {
347                     pr("%s already has a full fuel load.\n",
348                        prland(&item.land));
349                     continue;
350                 }
351                 tot_fuel = (oil_amt * 50 + pet_amt * 5);
352                 if (tot_fuel == 0) {
353                     pr("No fuel in the sector at %s!\n",
354                        xyas(sect.sct_x, sect.sct_y, player->cnum));
355                     continue;
356                 }
357                 move_amt = min(tot_fuel, fuel_amt);
358                 move_amt = min(move_amt, max_amt);
359
360                 if (move_amt == 0)
361                     continue;
362
363                 item.land.lnd_fuel += move_amt;
364
365                 fueled = 1;
366                 if ((pet_amt * 5) >= move_amt) {
367                     extra = ((float)move_amt / 5.0) - (move_amt / 5);
368                     if (extra > 0.0)
369                         putvar(V_PETROL,
370                                max((pet_amt - (move_amt / 5)) - 1, 0),
371                                (s_char *)&sect, EF_SECTOR);
372                     else
373                         putvar(V_PETROL,
374                                max((pet_amt - (move_amt / 5)), 0),
375                                (s_char *)&sect, EF_SECTOR);
376                 } else {
377                     putvar(V_PETROL, 0, (s_char *)&sect, EF_SECTOR);
378                     move_amt -= pet_amt * 5;
379                     extra = ((float)move_amt / 50.0) - (move_amt / 50);
380                     putvar(V_OIL, max(oil_amt - (move_amt / 50), 0),
381                            (s_char *)&sect, EF_SECTOR);
382                     if (extra > 0.0)
383                         putvar(V_OIL,
384                                max((oil_amt - (move_amt / 50)) - 1, 0),
385                                (s_char *)&sect, EF_SECTOR);
386                     else
387                         putvar(V_OIL,
388                                max((oil_amt - (move_amt / 50)), 0),
389                                (s_char *)&sect, EF_SECTOR);
390                 }
391
392                 /* load plague */
393                 if (getvar(V_PSTAGE, (s_char *)&sect, EF_SECTOR) ==
394                     PLG_INFECT && getvar(V_PSTAGE,
395                                          (s_char *)&item.land,
396                                          EF_LAND) == PLG_HEALTHY)
397                     putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&item.land,
398                            EF_LAND);
399
400                 putsect(&sect);
401                 putland(item.land.lnd_uid, &item.land);
402             } else {            /* not in a sector */
403                 if (!player->argp[4])
404                     pr("%s is not in a supplied sector\n",
405                        prland(&item.land));
406                 if (!snxtitem(&ltender, EF_LAND,
407                               getstarg(player->argp[4], "Supply unit? ",
408                                        buf)))
409                     continue;
410
411                 if (!check_land_ok(&item.land))
412                     continue;
413
414                 if (!nxtitem(&ltender, (s_char *)&item2))
415                     continue;
416
417                 if (!(lchr[(int)item2.land.lnd_type].l_flags & L_SUPPLY)) {
418                     pr("%s is not a supply unit!\n", prland(&item2.land));
419                     continue;
420                 }
421                 if (item2.land.lnd_own != player->cnum) {
422                     pr("You don't own that unit!\n");
423                     continue;
424                 }
425
426                 if ((item2.land.lnd_x != item.land.lnd_x) ||
427                     (item2.land.lnd_y != item.land.lnd_y)) {
428                     pr("Not in the same sector!\n");
429                     continue;
430                 }
431                 land_fuel = item.land.lnd_fuel;
432                 oil_amt = getvar(V_OIL, (s_char *)&item2.land, EF_LAND);
433                 pet_amt = getvar(V_PETROL, (s_char *)&item2.land, EF_LAND);
434                 max_amt = item.land.lnd_fuelc - land_fuel;
435
436                 if (max_amt == 0) {
437                     pr("%s already has a full fuel load.\n",
438                        prland(&item.land));
439                     continue;
440                 }
441                 tot_fuel = oil_amt * 50 + pet_amt * 5;
442                 move_amt = min(tot_fuel, fuel_amt);
443                 move_amt = min(move_amt, max_amt);
444
445                 if (move_amt == 0)
446                     continue;
447
448                 item.land.lnd_fuel += move_amt;
449
450                 fueled = 1;
451                 if ((pet_amt * 5) >= move_amt) {
452                     extra = ((float)move_amt / 5.0) - (move_amt / 5);
453                     if (extra > 0.0)
454                         putvar(V_PETROL,
455                                max((pet_amt - (move_amt / 5)) - 1, 0),
456                                (s_char *)&item2.land, EF_LAND);
457                     else
458                         putvar(V_PETROL,
459                                max((pet_amt - (move_amt / 5)), 0),
460                                (s_char *)&item2.land, EF_LAND);
461                 } else {
462                     putvar(V_PETROL, 0, (s_char *)&item2.land, EF_LAND);
463                     move_amt -= pet_amt * 5;
464                     extra = ((float)move_amt / 50.0) - (move_amt / 50);
465                     putvar(V_OIL, max(oil_amt - (move_amt / 50), 0),
466                            (s_char *)&item2.land, EF_LAND);
467                     if (extra > 0.0)
468                         putvar(V_OIL,
469                                max((oil_amt - (move_amt / 50)) - 1, 0),
470                                (s_char *)&item2.land, EF_LAND);
471                     else
472                         putvar(V_OIL,
473                                max((oil_amt - (move_amt / 50)), 0),
474                                (s_char *)&item2.land, EF_LAND);
475                 }
476
477                 /* load plague */
478                 if (getvar(V_PSTAGE, (s_char *)&item2.land, EF_LAND) ==
479                     PLG_INFECT && getvar(V_PSTAGE,
480                                          (s_char *)&item.land,
481                                          EF_LAND) == PLG_HEALTHY)
482                     putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&item.land,
483                            EF_LAND);
484
485                 putland(item.land.lnd_uid, &item.land);
486                 /* quick hack -KHS */
487                 if (item2.land.lnd_uid == item.land.lnd_uid)
488                     item2.land.lnd_fuel = item.land.lnd_fuel;
489                 putland(item2.land.lnd_uid, &item2.land);
490             }
491             pr("%s", prland(&item.land));
492         }
493         if (fueled) {
494             pr(" takes on %d fuel in %s\n",
495                move_amt,
496                xyas(item.ship.shp_x, item.ship.shp_y, player->cnum));
497             if (player->cnum != item.ship.shp_own)
498                 wu(0, item.ship.shp_own,
499                    "%s takes on %d fuel in %s courtesy of %s\n",
500                    prship(&item.ship),
501                    move_amt,
502                    xyas(item.ship.shp_x, item.ship.shp_y,
503                         item.ship.shp_own), cname(player->cnum));
504         }
505     }
506     return RET_OK;
507 }