]> git.pond.sub.org Git - empserver/blob - src/lib/commands/scut.c
(payo, scuttle_tradeship, sdump): Disclose construction site only to
[empserver] / src / lib / commands / scut.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  *  scut.c: Scuttle ships, planes or land units
29  * 
30  *  Known contributors to this file:
31  *     
32  */
33
34 #include "misc.h"
35 #include "player.h"
36 #include "sect.h"
37 #include "news.h"
38 #include "var.h"
39 #include "xy.h"
40 #include "ship.h"
41 #include "land.h"
42 #include "plane.h"
43 #include "nat.h"
44 #include "nsc.h"
45 #include "deity.h"
46 #include "file.h"
47 #include "commands.h"
48 #include "optlist.h"
49
50 static void scuttle_land(struct lndstr *);
51
52 union item_u {
53     struct shpstr ship;
54     struct plnstr plane;
55     struct lndstr land;
56 };
57
58 int
59 scuttle_tradeship(struct shpstr *sp, int interactive)
60 {
61     extern int trade_1_dist;    /* less than this gets no money */
62     extern int trade_2_dist;    /* less than this gets trade_1 money */
63     extern int trade_3_dist;    /* less than this gets trade_2 money */
64     extern float trade_1;       /* return on trade_1 distance */
65     extern float trade_2;       /* return on trade_2 distance */
66     extern float trade_3;       /* return on trade_3 distance */
67     extern float trade_ally_bonus;      /* 20% bonus for trading with allies */
68     extern float trade_ally_cut;        /* 10% bonus for ally you trade with */
69     float cash = 0;
70     float ally_cash = 0;
71     int dist;
72     struct sctstr sect;
73     struct mchrstr *mp;
74     struct natstr *np;
75     s_char buf[512];
76     struct natstr *natp;
77
78     mp = &mchr[(int)sp->shp_type];
79     getsect(sp->shp_x, sp->shp_y, &sect);
80     if (sect.sct_own && sect.sct_type == SCT_HARBR) {
81         dist = mapdist(sp->shp_x, sp->shp_y,
82                        sp->shp_orig_x, sp->shp_orig_y);
83         /* Don't disclose distance to to pirates */
84         if (sp->shp_own == sp->shp_orig_own) {
85             if (interactive)
86                 pr("%s has gone %d sects\n", prship(sp), dist);
87             else
88                 wu(0, sp->shp_own, "%s has gone %d sects\n",
89                    prship(sp), dist);
90         }
91         if (dist < trade_1_dist)
92             cash = 0;
93         else if (dist < trade_2_dist)
94             cash = (1.0 + trade_1 * ((float)dist));
95         else if (dist < trade_3_dist)
96             cash = (1.0 + trade_2 * ((float)dist));
97         else
98             cash = (1.0 + trade_3 * ((float)dist));
99         cash *= mp->m_cost;
100         cash *= (((float)sp->shp_effic) / 100.0);
101
102         if (sect.sct_own != sp->shp_own) {
103             cash *= (1.0 + trade_ally_bonus);
104             ally_cash = cash * trade_ally_cut;
105         }
106     }
107
108     if (!interactive && cash) {
109         natp = getnatp(sp->shp_own);
110         natp->nat_money += cash;
111         putnat(natp);
112         wu(0, sp->shp_own, "You just made $%d.\n", (int)cash);
113     } else if (!cash && !interactive) {
114         wu(0, sp->shp_own, "Unfortunately, you make $0 on this trade.\n");
115     } else if (cash && interactive) {
116         player->dolcost -= cash;
117     } else if (interactive && sp->shp_own == sp->shp_orig_own) {
118         pr("You won't get any money if you scuttle in %s!",
119            xyas(sp->shp_x, sp->shp_y, player->cnum));
120         sprintf(buf, "Are you sure you want to scuttle %s? ", prship(sp));
121         return confirm(buf);
122     }
123
124     if (ally_cash) {
125         np = getnatp(sect.sct_own);
126         np->nat_money += ally_cash;
127         putnat(np);
128         wu(0, sect.sct_own,
129            "Trade with %s nets you $%d at %s\n",
130            cname(sp->shp_own),
131            (int)ally_cash, xyas(sect.sct_x, sect.sct_y, sect.sct_own));
132         if (sp->shp_own != sp->shp_orig_own)
133             nreport(sp->shp_own, N_PIRATE_TRADE, sp->shp_orig_own, 1);
134         else
135             nreport(sp->shp_own, N_TRADE, sect.sct_own, 1);
136     } else if (sp->shp_own != sp->shp_orig_own)
137         nreport(sp->shp_own, N_PIRATE_KEEP, sp->shp_orig_own, 1);
138
139     return 1;
140 }
141
142 int
143 scut(void)
144 {
145     struct nstr_item ni;
146     union item_u item;
147     int type;
148     struct mchrstr *mp;
149     struct plchrstr *pp;
150     struct lchrstr *lp;
151     s_char *p;
152     s_char prompt[128];
153     s_char buf[1024];
154
155     if (!(p = getstarg(player->argp[1], "Ship, land, or plane? ", buf)))
156         return RET_SYN;
157     switch (*p) {
158     case 's':
159         type = EF_SHIP;
160         break;
161     case 'p':
162         type = EF_PLANE;
163         break;
164     case 'l':
165         type = EF_LAND;
166         break;
167     default:
168         pr("Ships, land units, or planes only! (s, l, p)\n");
169         return RET_SYN;
170     }
171     sprintf(prompt, "%s(s)? ", ef_nameof(type));
172     if ((p = getstarg(player->argp[2], prompt, buf)) == 0)
173         return RET_SYN;
174     if (!snxtitem(&ni, type, p))
175         return RET_SYN;
176     if (p && (isalpha(*p) || (*p == '*') || (*p == '~') || issector(p)
177               || islist(p))) {
178         s_char y_or_n[80], bbuf[80];
179
180         if (type == EF_SHIP) {
181             if (*p == '*')
182                 sprintf(bbuf, "all ships");
183             else if (*p == '~')
184                 sprintf(bbuf, "all unassigned ships");
185             else if (issector(p))
186                 sprintf(bbuf, "all ships in %s", p);
187             else if (isalpha(*p))
188                 sprintf(bbuf, "fleet %c", *p);
189             else
190                 sprintf(bbuf, "ships %s", p);
191         } else if (type == EF_LAND) {
192             if (*p == '*')
193                 sprintf(bbuf, "all land units");
194             else if (*p == '~')
195                 sprintf(bbuf, "all unassigned land units");
196             else if (issector(p))
197                 sprintf(bbuf, "all units in %s", p);
198             else if (isalpha(*p))
199                 sprintf(bbuf, "army %c", *p);
200             else
201                 sprintf(bbuf, "units %s", p);
202         } else {
203             if (*p == '*')
204                 sprintf(bbuf, "all planes");
205             else if (*p == '~')
206                 sprintf(bbuf, "all unassigned planes");
207             else if (issector(p))
208                 sprintf(bbuf, "all planes in %s", p);
209             else if (isalpha(*p))
210                 sprintf(bbuf, "wing %c", *p);
211             else
212                 sprintf(bbuf, "planes %s", p);
213         }
214         sprintf(y_or_n, "Really scuttle %s? ", bbuf);
215         if (!confirm(y_or_n))
216             return RET_FAIL;
217     }
218     while (nxtitem(&ni, (s_char *)&item)) {
219         if (!player->owner)
220             continue;
221         if (opt_MARKET) {
222             if (ontradingblock(type, (int *)&item.ship)) {
223                 pr("You cannot scuttle an item on the trading block!\n");
224                 continue;
225             }
226         }
227
228         if (type == EF_SHIP) {
229             mp = &mchr[(int)item.ship.shp_type];
230             if (opt_TRADESHIPS) {
231                 if (mp->m_flags & M_TRADE)
232                     if (!scuttle_tradeship(&item.ship, 1))
233                         continue;
234             }
235             pr("%s", prship(&item.ship));
236             scuttle_ship(&item.ship);
237         } else if (type == EF_LAND) {
238             if (item.land.lnd_ship >= 0) {
239                 pr("%s is on a ship, and cannot be scuttled!\n",
240                    prland(&item.land));
241                 continue;
242             }
243             lp = &lchr[(int)item.land.lnd_type];
244             pr("%s", prland(&item.land));
245             scuttle_land(&item.land);
246         } else {
247             pp = &plchr[(int)item.plane.pln_type];
248             pr("%s", prplane(&item.plane));
249             if (item.plane.pln_ship >= 0) {
250                 struct shpstr ship;
251
252                 getship(item.plane.pln_ship, &ship);
253                 take_plane_off_ship(&item.plane, &ship);
254             }
255             makelost(EF_PLANE, item.plane.pln_own, item.plane.pln_uid,
256                      item.plane.pln_x, item.plane.pln_y);
257             item.plane.pln_own = 0;
258             putplane(item.plane.pln_uid, (s_char *)&item.plane);
259         }
260         pr(" scuttled in %s\n",
261            xyas(item.ship.shp_x, item.ship.shp_y, player->cnum));
262     }
263
264     return RET_OK;
265 }
266
267 void
268 scuttle_ship(struct shpstr *sp)
269 {
270     struct nstr_item ni;
271     struct sctstr sect;
272     struct plnstr plane;
273     struct lndstr land;
274
275     getsect(sp->shp_x, sp->shp_y, &sect);
276     snxtitem_all(&ni, EF_PLANE);
277     while (nxtitem(&ni, (s_char *)&plane)) {
278         if (plane.pln_own == 0)
279             continue;
280         if (plane.pln_ship == sp->shp_uid) {
281             plane.pln_ship = -1;
282             if (sect.sct_own != sp->shp_own) {
283                 wu(0, plane.pln_own, "Plane %d scuttled in %s\n",
284                    plane.pln_uid,
285                    xyas(plane.pln_x, plane.pln_y, plane.pln_own));
286                 makelost(EF_PLANE, plane.pln_own, plane.pln_uid,
287                          plane.pln_x, plane.pln_y);
288                 plane.pln_own = 0;
289             } else {
290                 wu(0, plane.pln_own,
291                    "Plane %d transferred off ship %d to %s\n",
292                    plane.pln_uid, sp->shp_uid,
293                    xyas(plane.pln_x, plane.pln_y, plane.pln_own));
294             }
295             putplane(plane.pln_uid, (s_char *)&plane);
296         }
297     }
298     snxtitem_all(&ni, EF_LAND);
299     while (nxtitem(&ni, (s_char *)&land)) {
300         if (land.lnd_own == 0)
301             continue;
302         if (land.lnd_ship == sp->shp_uid) {
303             land.lnd_ship = -1;
304             if (sect.sct_own == sp->shp_own) {
305                 wu(0, land.lnd_own,
306                    "Land unit %d transferred off ship %d to %s\n",
307                    land.lnd_uid, sp->shp_uid,
308                    xyas(land.lnd_x, land.lnd_y, land.lnd_own));
309                 putland(land.lnd_uid, (s_char *)&land);
310             } else
311                 scuttle_land(&land);
312         }
313     }
314     makelost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y);
315     sp->shp_own = 0;
316     putship(sp->shp_uid, sp);
317 }
318
319 static void
320 scuttle_land(struct lndstr *lp)
321 {
322     struct nstr_item ni;
323     struct sctstr sect;
324     struct plnstr plane;
325     struct lndstr land;
326
327     getsect(lp->lnd_x, lp->lnd_y, &sect);
328     snxtitem_all(&ni, EF_PLANE);
329     while (nxtitem(&ni, (s_char *)&plane)) {
330         if (plane.pln_own == 0)
331             continue;
332         if (plane.pln_land == lp->lnd_uid) {
333             plane.pln_land = -1;
334             if (sect.sct_own != lp->lnd_own) {
335                 wu(0, plane.pln_own, "Plane %d scuttled in %s\n",
336                    plane.pln_uid,
337                    xyas(plane.pln_x, plane.pln_y, plane.pln_own));
338                 makelost(EF_PLANE, plane.pln_own, plane.pln_uid,
339                          plane.pln_x, plane.pln_y);
340                 plane.pln_own = 0;
341             } else {
342                 wu(0, plane.pln_own,
343                    "Plane %d transferred off unit %d to %s\n",
344                    plane.pln_uid, lp->lnd_uid,
345                    xyas(plane.pln_x, plane.pln_y, plane.pln_own));
346             }
347             putplane(plane.pln_uid, (s_char *)&plane);
348         }
349     }
350     snxtitem_all(&ni, EF_LAND);
351     while (nxtitem(&ni, (s_char *)&land)) {
352         if (land.lnd_own == 0)
353             continue;
354         if (land.lnd_land == lp->lnd_uid) {
355             land.lnd_land = -1;
356             if (sect.sct_own == lp->lnd_own) {
357                 wu(0, land.lnd_own,
358                    "Land unit %d transferred off unit %d to %s\n",
359                    land.lnd_uid, lp->lnd_uid,
360                    xyas(land.lnd_x, land.lnd_y, land.lnd_own));
361                 putland(land.lnd_uid, (s_char *)&land);
362             } else
363                 scuttle_land(&land);
364         }
365     }
366     makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y);
367     lp->lnd_own = 0;
368     putland(lp->lnd_uid, lp);
369 }