]> git.pond.sub.org Git - empserver/blob - src/lib/commands/cede.c
f2ec792026e02624efecfeeffa140a0811236aef
[empserver] / src / lib / commands / cede.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2006, 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  *  cede.c: Give a sector to a neighbor
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare
32  *     Thomas Ruschak
33  */
34
35 #include <config.h>
36
37 #include "misc.h"
38 #include "player.h"
39 #include "xy.h"
40 #include "sect.h"
41 #include "nsc.h"
42 #include "nat.h"
43 #include "path.h"
44 #include "file.h"
45 #include "plane.h"
46 #include "land.h"
47 #include "ship.h"
48 #include "nuke.h"
49 #include "commands.h"
50
51 static void cede_hdr(void);
52 static int cede_sect(struct nstr_sect *, natid);
53 static int cede_ship(struct nstr_item *, natid);
54 static void grab_sect(struct sctstr *, natid);
55 static void grab_ship(struct shpstr *, natid);
56
57 int
58 cede(void)
59 {
60     static int sct_or_shp[] = { EF_SECTOR, EF_SHIP, EF_BAD };
61     natid to;
62     int n;
63     int is_sector = 0, is_ship = 0;
64     s_char *p;
65     struct nstr_sect ns;
66     struct nstr_item ni;
67     struct natstr *natp;
68     s_char buf[1024];
69
70     if ((p = getstarg(player->argp[1], "Cede what? ", buf)) == 0)
71         return RET_SYN;
72     if (snxtsct(&ns, p))
73         is_sector = 1;
74     if (snxtitem(&ni, EF_SHIP, p))
75         is_ship = 1;
76     if (!is_sector && !is_ship)
77         return RET_SYN;
78     if ((n = natarg(player->argp[2], "to which country? ")) < 0)
79         return RET_SYN;
80     if (is_sector && is_ship) {
81         int type;
82
83         if ((p =
84              getstarg(player->argp[3], "Cede sectors or ships (se, sh)? ",
85                       buf)) == 0)
86             return RET_FAIL;
87         if (strlen(p) > 4)
88             p[2] = 0;
89         type = ef_byname_from(p, sct_or_shp);
90         if (type < 0) {
91             pr("Please type 'se' or 'sh'!\n");
92             return RET_FAIL;
93         }
94     }
95
96
97     if (n == player->cnum) {
98         pr("Giving something to yourself?\n");
99         return RET_FAIL;
100     }
101     natp = getnatp(n);
102     if (natp->nat_stat != STAT_ACTIVE) {
103         pr("You can only give to normal countries...\n");
104         return RET_FAIL;
105     }
106     if (getrel(natp, player->cnum) < FRIENDLY) {
107         pr("You can only cede to a country that is friendly towards you...\n");
108         return RET_FAIL;
109     }
110     to = n;
111
112     if (is_sector)
113         return cede_sect(&ns, to);
114     else
115         return cede_ship(&ni, to);
116 }
117
118 static int
119 cede_sect(struct nstr_sect *ns, natid to)
120 {
121     struct sctstr sect, osect;
122     int nsect;
123     int n, bad;
124     s_char dirstr[20];
125     int off_x, off_y;
126     struct nstr_item ni;
127     struct shpstr ship;
128
129     prdate();
130     for (n = 1; n <= 6; n++)
131         dirstr[n] = dirch[n];
132     dirstr[0] = '.';
133     dirstr[7] = '$';
134     dirstr[8] = '\0';
135     nsect = 0;
136     while (nxtsct(ns, &sect)) {
137         if (!player->owner)
138             continue;
139         if (sect.sct_mobil == 0) {
140             pr("%s has no mobility and cannot be ceded\n",
141                xyas(sect.sct_x, sect.sct_y, player->cnum));
142             continue;
143         }
144
145         bad = 1;
146         for (n = 1; n <= 6; n++) {      /* Directions */
147             off_x = sect.sct_x + diroff[n][0];
148             off_y = sect.sct_y + diroff[n][1];
149
150             if (!getsect(off_x, off_y, &osect))
151                 continue;
152             if ((osect.sct_own == to) && (osect.sct_mobil))
153                 bad = 0;
154             if ((osect.sct_own == to) &&
155                 has_units_with_mob(osect.sct_x, osect.sct_y, to))
156                 bad = 0;
157         }
158         snxtitem_all(&ni, EF_SHIP);
159         while (nxtitem(&ni, &ship)) {
160             if ((ship.shp_own == to) &&
161                 ((ship.shp_x == sect.sct_x) && (ship.shp_y == sect.sct_y)))
162                 bad = 0;
163         }
164         if (bad) {
165             pr("%s has no sector with mobility adjacent to or ship in %s!\n", cname(to), xyas(sect.sct_x, sect.sct_y, player->cnum));
166             continue;
167         }
168
169         if (nsect++ == 0)
170             cede_hdr();
171
172         grab_sect(&sect, to);
173         putsect(&sect);
174         pr("  %s %d%% ceded\n", xyas(sect.sct_x, sect.sct_y, player->cnum),
175            (int)sect.sct_effic);
176         wu(0, (natid)to, "%s ceded to you by %s\n",
177            xyas(sect.sct_x, sect.sct_y, to), cname(player->cnum));
178     }
179     pr("%d sector%s\n", nsect, splur(nsect));
180     return RET_OK;
181 }
182
183 static void
184 cede_hdr(void)
185 {
186     if (player->god)
187         pr("own ");
188     pr("  sect eff\n");
189 }
190
191
192
193 static void
194 grab_sect(struct sctstr *sp, natid to)
195 {
196     struct plnstr *pp;
197     struct lndstr *lp;
198     struct nukstr *np;
199     struct nstr_item ni;
200     struct plnstr p;
201     struct lndstr l;
202     struct nukstr nuk;
203
204     /* Wipe all the distribution info */
205     memset(sp->sct_dist, 0, sizeof(sp->sct_dist));
206     memset(sp->sct_del, 0, sizeof(sp->sct_del));
207     sp->sct_dist_x = sp->sct_x;
208     sp->sct_dist_y = sp->sct_y;
209
210     pp = &p;
211     snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y);
212     while (nxtitem(&ni, pp)) {
213         if (pp->pln_own == 0)
214             continue;
215         if (pp->pln_ship >= 0)
216             continue;
217         if (pp->pln_own != player->cnum)
218             continue;
219         if (pp->pln_flags & PLN_LAUNCHED)
220             continue;
221
222         wu(0, to, "\t%s ceded to you by %s\n",
223            prplane(pp), cname(player->cnum));
224         makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y);
225         pp->pln_own = to;
226         makenotlost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x,
227                     pp->pln_y);
228         pp->pln_mobil = 0;
229         pp->pln_mission = 0;
230         putplane(pp->pln_uid, pp);
231     }
232
233     np = &nuk;
234     snxtitem_xy(&ni, EF_NUKE, sp->sct_x, sp->sct_y);
235     while (nxtitem(&ni, np)) {
236         if (np->nuk_own == 0)
237             continue;
238
239         wu(0, to, "\tnuclear stockpile #%d ceded to you by %s\n",
240            np->nuk_uid, cname(player->cnum));
241         makelost(EF_NUKE, np->nuk_own, np->nuk_uid, np->nuk_x, np->nuk_y);
242         np->nuk_own = to;
243         makenotlost(EF_NUKE, np->nuk_own, np->nuk_uid, np->nuk_x,
244                     np->nuk_y);
245         putnuke(ni.cur, np);
246     }
247
248     lp = &l;
249     snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
250     while (nxtitem(&ni, lp)) {
251         if (lp->lnd_own == 0)
252             continue;
253         if (lp->lnd_ship == 0)
254             continue;
255         if (lp->lnd_own != player->cnum)
256             continue;
257
258         wu(0, to, "\t%s ceded to you by %s\n", prland(lp),
259            cname(player->cnum));
260         makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y);
261         makenotlost(EF_LAND, to, lp->lnd_uid, lp->lnd_x, lp->lnd_y);
262         lp->lnd_own = to;
263         lp->lnd_mobil = 0;
264         lp->lnd_mission = 0;
265         putland(ni.cur, lp);
266     }
267
268     sp->sct_avail = 0;
269
270     if (sp->sct_oldown == to) {
271         sp->sct_che = 0;        /* FIXME where do these guys go? */
272         sp->sct_che_target = 0;
273         sp->sct_loyal = 0;
274     }
275
276     if (sp->sct_oldown == to)
277         sp->sct_loyal = 0;
278     else                        /* people don't like being given away */
279         sp->sct_loyal = 50;
280
281     sp->sct_dist_x = sp->sct_x;
282     sp->sct_dist_y = sp->sct_y;
283     makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y);
284     makenotlost(EF_SECTOR, to, 0, sp->sct_x, sp->sct_y);
285     if (sp->sct_oldown == sp->sct_own)
286         sp->sct_oldown = to;
287     sp->sct_own = to;
288     sp->sct_mobil = 0;
289 }
290
291 static int
292 cede_ship(struct nstr_item *ni, natid to)
293 {
294     struct shpstr ship;
295     struct shpstr tship;
296     struct sctstr sect;
297     struct nstr_item tni;
298     int nships = 0;
299     int bad = 0;
300
301     while (nxtitem(ni, &ship)) {
302
303         if (!player->owner || ship.shp_own == 0)
304             continue;
305
306         bad = 1;
307         snxtitem_xy(&tni, EF_SHIP, ship.shp_x, ship.shp_y);
308         while (nxtitem(&tni, &tship) && bad)
309             if (tship.shp_own == to)
310                 bad = 0;
311
312         getsect(ship.shp_x, ship.shp_y, &sect);
313         if (bad && (sect.sct_own != to)) {
314             pr("%s isn't in a %s sector, and is not with a %s ship!\n",
315                prship(&ship), cname(to), cname(to));
316             continue;
317         }
318         grab_ship(&ship, to);
319         putship(ship.shp_uid, &ship);
320         nships++;
321         wu(0, to, "%s ceded to you by %s\n",
322            prship(&ship), cname(player->cnum));
323         pr("%s ceded to %s\n", prship(&ship), cname(to));
324     }
325     pr("    %d ship%s\n", nships, splur(nships));
326
327     return RET_OK;
328 }
329
330 static void
331 grab_ship(struct shpstr *sp, natid to)
332 {
333     struct plnstr *pp;
334     struct lndstr *lp;
335     struct nstr_item ni;
336     struct plnstr p;
337     struct lndstr l;
338
339     pp = &p;
340     snxtitem_xy(&ni, EF_PLANE, sp->shp_x, sp->shp_y);
341     while (nxtitem(&ni, pp)) {
342         if (pp->pln_own == 0)
343             continue;
344         if (pp->pln_flags & PLN_LAUNCHED)
345             continue;
346         if (pp->pln_ship != sp->shp_uid)
347             continue;
348         if (pp->pln_own != player->cnum)
349             continue;
350
351         wu(0, to, "\t%s ceded to you by %s\n",
352            prplane(pp), cname(player->cnum));
353         makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y);
354         pp->pln_own = to;
355         makenotlost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x,
356                     pp->pln_y);
357         pp->pln_mobil = 0;
358         pp->pln_mission = 0;
359         putplane(pp->pln_uid, pp);
360     }
361
362     lp = &l;
363     snxtitem_xy(&ni, EF_LAND, sp->shp_x, sp->shp_y);
364     while (nxtitem(&ni, lp)) {
365         if (lp->lnd_own == 0)
366             continue;
367         if (lp->lnd_ship != sp->shp_uid)
368             continue;
369         if (lp->lnd_own != player->cnum)
370             continue;
371
372         wu(0, to, "\t%s ceded to you by %s\n",
373            prland(lp), cname(player->cnum));
374         makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y);
375         makenotlost(EF_LAND, to, lp->lnd_uid, lp->lnd_x, lp->lnd_y);
376         lp->lnd_own = to;
377         lp->lnd_mobil = 0;
378         lp->lnd_mission = 0;
379         putland(ni.cur, lp);
380     }
381
382     makelost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y);
383     sp->shp_own = to;
384     makenotlost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y);
385 }