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