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