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