]> git.pond.sub.org Git - empserver/blob - src/lib/commands/tran.c
(move_ground): Remove superflous parameter `mobility'. Callers
[empserver] / src / lib / commands / tran.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  *  tran.c: Transport nuclear devices and planes
29  * 
30  *  Known contributors to this file:
31  *     Steve McClure, 2000
32  *  
33  */
34
35 #ifdef Rel4
36 #include <string.h>
37 #endif /* Rel4 */
38 #include "misc.h"
39 #include "player.h"
40 #include "var.h"
41 #include "sect.h"
42 #include "nuke.h"
43 #include "xy.h"
44 #include "nsc.h"
45 #include "plane.h"
46 #include "ship.h"
47 #include "file.h"
48 #include "nat.h"
49 #include "land.h"
50 #include "commands.h"
51
52 #include <stdio.h>
53
54 static int tran_map(s_char *what, coord curx, coord cury, s_char *arg);
55 static int tran_nuke(void);
56 static int tran_plane(void);
57
58 int
59 tran(void)
60 {
61     s_char *what;
62     s_char buf[1024];
63
64     what =
65         getstarg(player->argp[1], "transport what (nuke or plane): ", buf);
66     if (what == 0)
67         return RET_SYN;
68     if (*what == 'n')
69         return tran_nuke();
70     else if (*what == 'p')
71         return tran_plane();
72     return RET_SYN;
73 }
74
75 /*
76  * Kinda silly; only moves the first nuke.
77  * Maybe nukes should be made into commodities?
78  */
79 static int
80 tran_nuke(void)
81 {
82     struct nchrstr *ncp;
83     int len;
84     coord x, y;
85     coord dstx, dsty;
86     int found;
87     s_char *p;
88     int i;
89     int nuketype;
90     int moving;
91     struct nukstr nuke;
92     struct sctstr sect;
93     struct sctstr endsect;
94     int mcost, dam;
95     struct nstr_item nstr;
96     s_char buf[1024];
97
98     if (!(p = getstarg(player->argp[2], "from sector : ", buf)))
99         return RET_SYN;
100     if (!sarg_xy(p, &x, &y))
101         return RET_SYN;
102     if (!getsect(x, y, &sect) || !player->owner) {
103         pr("Not yours\n");
104         return RET_FAIL;
105     }
106 #if 0
107     if (!snxtitem_xy(&nstr, EF_NUKE, sect.sct_x, sect.sct_y)) {
108         pr("There are no nukes in %s\n",
109            xyas(sect.sct_x, sect.sct_y, player->cnum));
110         return RET_FAIL;
111     }
112 #else
113     snxtitem_xy(&nstr, EF_NUKE, sect.sct_x, sect.sct_y);
114 #endif
115     found = 0;
116     while (nxtitem(&nstr, (caddr_t)&nuke)) {
117         if (player->owner) {
118             found = 1;
119             break;
120         }
121     }
122     if (!found) {
123         pr("There are no nukes in %s\n",
124            xyas(sect.sct_x, sect.sct_y, player->cnum));
125         return RET_FAIL;
126     }
127     if (!(p = getstarg(player->argp[3], "warhead type : ", buf)))
128         return RET_SYN;
129     if (!check_sect_ok(&sect))
130         return RET_FAIL;
131     len = strlen(p);
132     for (i = 0, ncp = nchr; i < N_MAXNUKE; i++, ncp++) {
133         if (strncmp(ncp->n_name, p, len) == 0)
134             break;
135     }
136     if (i >= N_MAXNUKE) {
137         pr("No such nuke type!\n");
138         return RET_SYN;
139     }
140     nuketype = i;
141     if (!nuke.nuk_types[nuketype]) {
142         pr("No %s nukes in %s\n",
143            ncp->n_name, xyas(sect.sct_x, sect.sct_y, player->cnum));
144         return RET_FAIL;
145     }
146     p = getstarg(player->argp[4], "number of warheads : ", buf);
147     if (!check_sect_ok(&sect))
148         return RET_FAIL;
149     if (p == 0 || *p == 0 || (moving = atoi(p)) < 0)
150         return RET_FAIL;
151     if (moving > nuke.nuk_types[nuketype]) {
152         moving = nuke.nuk_types[nuketype];
153         if (moving)
154             pr("only moving %d\n", moving);
155         else
156             return RET_FAIL;
157     }
158     /*
159      * military control necessary to move
160      * goodies in occupied territory.
161      */
162     if (sect.sct_oldown != player->cnum) {
163         int tot_mil = 0;
164         struct nstr_item ni;
165         struct lndstr land;
166         snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y);
167         while (nxtitem(&ni, (s_char *)&land)) {
168             if (land.lnd_own == player->cnum)
169                 tot_mil += total_mil(&land);
170         }
171         if ((getvar(V_MILIT, (s_char *)&sect, EF_SECTOR) + tot_mil) * 10
172             < getvar(V_CIVIL, (s_char *)&sect, EF_SECTOR)) {
173             pr("Military control required to move goods.\n");
174             return RET_FAIL;
175         }
176     }
177     dam = 0;
178     mcost = move_ground((s_char *)&nuke, &sect, &endsect,
179                         (double)ncp->n_weight * moving,
180                         player->argp[5], tran_map, 0, &dam);
181
182     if (mcost < 0)
183         return 0;
184
185     if (mcost > 0)
186         pr("Total movement cost = %d\n", mcost);
187     else
188         pr("No mobility used\n");
189
190     dstx = endsect.sct_x;
191     dsty = endsect.sct_y;
192     /*
193      * decrement mobility from src sector
194      */
195     getsect(nuke.nuk_x, nuke.nuk_y, &sect);
196     sect.sct_mobil -= mcost;
197     if (sect.sct_mobil < 0)
198         sect.sct_mobil = 0;
199     putsect(&sect);
200     /*
201      * update old nuke
202      */
203     if (!getnuke(nuke.nuk_uid, &nuke)) {
204         pr("Could not find that stockpile again.\n");
205         return RET_FAIL;
206     }
207     if (nuke.nuk_types[nuketype] < moving || nuke.nuk_own != player->cnum) {
208         pr("Stockpile changed!\n");
209         return RET_FAIL;
210     }
211     nuk_delete(&nuke, nuketype, moving);
212     nuk_add(dstx, dsty, nuketype, moving);
213     return RET_OK;
214 }
215
216 static int
217 tran_plane(void)
218 {
219     int srcx, srcy;
220     int dstx, dsty;
221     int mcost;
222     int weight, count;
223     int first;
224     int type, dam;
225     struct nstr_item nstr;
226     struct plnstr plane;
227     struct sctstr sect;
228     struct sctstr endsect;
229
230     first = 1;
231     weight = 0;
232     count = 0;
233     if (!snxtitem(&nstr, EF_PLANE, player->argp[2]))
234         return RET_SYN;
235     /*
236      * First do some sanity checks: make sure that they are all in the,
237      * same sector, not on ships, owned, etc.
238      * No one could seriously want to move planes in parallel from
239      * several sectors!
240      */
241     while (nxtitem(&nstr, (s_char *)&plane)) {
242         if (!player->owner)
243             continue;
244         type = plane.pln_type;
245         if (plane.pln_ship >= 0) {
246             pr("%s is at sea and can't be transported\n", prplane(&plane));
247             return RET_FAIL;
248         } else if (plane.pln_harden != 0) {
249             pr("%s has been hardened and can't be transported\n",
250                prplane(&plane));
251             return RET_FAIL;
252         } else if ((plane.pln_flags & PLN_LAUNCHED) &&
253                    (plchr[type].pl_flags & P_O)) {
254             pr("%s is in space and can't be transported\n",
255                prplane(&plane));
256             return RET_FAIL;
257         }
258         if (first == 1) {
259             srcx = plane.pln_x;
260             srcy = plane.pln_y;
261             first = 0;
262         } else {
263             if (plane.pln_x != srcx || plane.pln_y != srcy) {
264                 pr("All planes must be in the same sector.\n");
265                 return RET_FAIL;
266             }
267         }
268         weight += plchr[type].pl_lcm + (plchr[type].pl_hcm * 2);
269         ++count;
270     }
271     if (first == 1) {
272         /* no planes */
273         return RET_FAIL;
274     }
275     getsect(srcx, srcy, &sect);
276     /*
277      * military control necessary to move
278      * goodies in occupied territory.
279      */
280     if (sect.sct_oldown != player->cnum) {
281         int tot_mil = 0;
282         struct nstr_item ni;
283         struct lndstr land;
284         snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y);
285         while (nxtitem(&ni, (s_char *)&land))
286             tot_mil += total_mil(&land);
287         if ((getvar(V_MILIT, (s_char *)&sect, EF_SECTOR) + tot_mil) * 10
288             < getvar(V_CIVIL, (s_char *)&sect, EF_SECTOR)) {
289             pr("Military control required to move goods.\n");
290             return RET_FAIL;
291         }
292     }
293     dam = 1;
294     mcost = move_ground((s_char *)&plane, &sect, &endsect,
295                         (double)weight,
296                         player->argp[3], tran_map, 0, &dam);
297     dam /= count;
298     if (mcost < 0)
299         return 0;
300
301     dstx = endsect.sct_x;
302     dsty = endsect.sct_y;
303     snxtitem_rewind(&nstr);
304     while (nxtitem(&nstr, (s_char *)&plane)) {
305         if (!player->owner)
306             continue;
307         if (dam) {
308             planedamage(&plane, dam);
309             pr("\t%s takes %d\n", prplane(&plane), dam);
310         }
311         plane.pln_x = dstx;
312         plane.pln_y = dsty;
313         plane.pln_mission = 0;
314         putplane(plane.pln_uid, &plane);
315     }
316     if (mcost > 0)
317         pr("Total movement cost = %d\n", mcost);
318     else
319         pr("No mobility used\n");
320     sect.sct_mobil -= mcost;
321     if (sect.sct_mobil < 0)
322         sect.sct_mobil = 0;
323     putsect(&sect);
324     return RET_OK;
325 }
326
327 /*
328  * Pretty tacky, but it works.
329  * If more commands start doing this, then
330  * rewrite map to do the right thing.
331  */
332 /* I think this is no longer used, check subs/move.c:move_ground() */
333 /*ARGSUSED*/
334 static int
335 tran_map(s_char *what, coord curx, coord cury, s_char *arg)
336 {
337     player->argp[1] = arg;
338     player->condarg = 0;
339     return map();
340 }