]> git.pond.sub.org Git - empserver/blob - src/lib/commands/expl.c
983a548149901cf2337037b606cf56c9a1f6269b
[empserver] / src / lib / commands / expl.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  *  expl.c: Take over unoccupied sectors
29  * 
30  *  Known contributors to this file:
31  *     Jeff Wallace, 1989
32  */
33
34 #include <config.h>
35
36 #include "misc.h"
37 #include "player.h"
38 #include "plague.h"
39 #include "sect.h"
40 #include "xy.h"
41 #include "nsc.h"
42 #include "item.h"
43 #include "file.h"
44 #include "nat.h"
45 #include "optlist.h"
46 #include "commands.h"
47
48 static int explore_map(s_char *what, coord curx, coord cury, s_char *arg);
49
50 int
51 explore(void)
52 {
53     int amount;
54     struct sctstr sect;
55     struct sctstr endsect;
56     struct sctstr start;
57     struct sctstr chksect;
58     double weight;
59     int mcost, dam;
60     int infected;
61     i_type vtype;
62     int amt_src;
63     int amt_dst;
64     struct ichrstr *ip;
65     int work;
66     int loyal;
67     int own, mob;
68     int justtook;
69     coord x, y;
70     s_char *p;
71     int n;
72     int left;
73     s_char buf[1024];
74     s_char prompt[128];
75
76     if (!(ip = whatitem(player->argp[1], "explore with what? (civ/mil) ")))
77         return RET_SYN;
78     vtype = ip->i_vtype;
79     if ((vtype != I_CIVIL) && (vtype != I_MILIT)) {
80         pr("You can only explore with civs and mil.\n");
81         return RET_FAIL;
82     }
83     if ((p = getstarg(player->argp[2], "from sector : ", buf)) == 0)
84         return RET_SYN;
85     if (!sarg_xy(p, &x, &y))
86         return RET_SYN;
87     if (!getsect(x, y, &sect) || !player->owner) {
88         pr("Not yours\n");
89         return RET_FAIL;
90     }
91     infected = sect.sct_pstage == PLG_INFECT;
92     if ((amt_src = sect.sct_item[vtype]) <= 0) {
93         pr("No %s in %s\n", ip->i_name,
94            xyas(sect.sct_x, sect.sct_y, player->cnum));
95         return RET_SYN;
96     }
97     own = sect.sct_own;
98     mob = (int)sect.sct_mobil;
99     if (vtype == I_CIVIL && sect.sct_oldown != own) {
100         pr("You can't explore with conquered populace!\n");
101         return RET_SYN;
102     }
103     if (mob <= 0) {
104         pr("No mobility in %s\n",
105            xyas(sect.sct_x, sect.sct_y, player->cnum));
106         return RET_SYN;
107     }
108
109     /* only used when moving civs; but prevent spurious compiler warnings */
110     work = sect.sct_work;
111     loyal = sect.sct_loyal;
112     if (vtype == I_CIVIL && work != 100)
113         pr("Warning: civil unrest\n");
114
115     sprintf(prompt, "Number of %s to explore with? (max %d) ",
116             ip->i_name, amt_src);
117     amount = onearg(player->argp[3], prompt);
118     if (!check_sect_ok(&sect))
119         return RET_FAIL;
120     if (amount > amt_src) {
121         amount = amt_src;
122         pr("Only exploring with %d.\n", amount);
123     }
124
125     if (!want_to_abandon(&sect, vtype, amount, 0)) {
126         pr("Explore cancelled.\n");
127         return RET_FAIL;
128     }
129
130     if (!check_sect_ok(&sect))
131         return RET_FAIL;
132
133     if (amount <= 0)
134         return RET_SYN;
135     weight = amount * ip->i_lbs;
136     /* remove commodities from source sector */
137     getsect(x, y, &start);
138     amt_src = start.sct_item[vtype];
139     amt_src -= amount;
140     if (amt_src < 0) {
141         pr("%s in %s are gone!\n", ip->i_name,
142            xyas(start.sct_x, start.sct_y, player->cnum));
143         return RET_OK;
144     }
145     start.sct_item[vtype] = amt_src;
146     start.sct_flags |= MOVE_IN_PROGRESS;
147     putsect(&start);
148     /*
149      * Now parse the path and return ending sector.
150      */
151     dam = 1;
152     mcost = move_ground((s_char *)ip, &sect, &endsect,
153                         weight, player->argp[4],
154                         explore_map, 1, &dam);
155
156     if (dam) {
157         left = effdamage(amount, dam);
158         if (left < amount) {
159             if (left) {
160                 pr("%d of the %s you were exploring with were destroyed!\nOnly %d %s made it to %s\n", amount - left, ip->i_name, left, ip->i_name, xyas(endsect.sct_x, endsect.sct_y, player->cnum));
161             } else {
162                 pr("All of the %s you were exploring with were destroyed!\n", ip->i_name);
163             }
164             amount = left;
165         }
166     }
167     if (mcost > 0)
168         pr("Total movement cost = %d", mcost);
169     else
170         pr("No mobility used");
171
172     if (mcost < 0) {
173         pr("\nExplore aborted");
174         getsect(start.sct_x, start.sct_y, &sect);
175         sect.sct_mobil = (u_char)mob;
176     } else {
177         /* Charge mobility */
178         getsect(sect.sct_x, sect.sct_y, &sect);
179         n = sect.sct_mobil - mcost;
180         if (n < 0)
181             n = 0;
182         sect.sct_mobil = (u_char)n;
183         pr(", %d mob left in %s", sect.sct_mobil,
184            xyas(sect.sct_x, sect.sct_y, player->cnum));
185         putsect(&sect);
186         getsect(endsect.sct_x, endsect.sct_y, &sect);
187     }
188     pr("\n");
189     justtook = 0;
190
191     /*
192      *      Check for a multitude of problems
193      */
194     getsect(endsect.sct_x, endsect.sct_y, &chksect);
195     if (amount <= 0) {
196         getsect(start.sct_x, start.sct_y, &start);
197         sect.sct_flags &= ~MOVE_IN_PROGRESS;
198         putsect(&sect);
199         return RET_FAIL;
200     }
201     if (chksect.sct_type == '.') {
202         pr("Bridge disappeared!\n");
203         getsect(start.sct_x, start.sct_y, &start);
204         start.sct_flags &= ~MOVE_IN_PROGRESS;
205         putsect(&start);
206         return RET_FAIL;
207     }
208     if (!player->god && chksect.sct_own && chksect.sct_own != player->cnum
209         && chksect.sct_type != SCT_SANCT) {
210         pr("Somebody beat you there!\n");
211         /* Send them back home */
212         getsect(start.sct_x, start.sct_y, &sect);
213         if (sect.sct_own != own) {
214             pr("Someone captured the sector you started from!\n");
215             pr("Your exploring people die of disappointment!\n");
216             sect.sct_flags &= ~MOVE_IN_PROGRESS;
217             putsect(&sect);
218             return RET_FAIL;
219         }
220     }
221
222     if (!player->god && !player->owner && sect.sct_type != SCT_SANCT) {
223         takeover(&sect, player->cnum);
224         justtook = 1;
225         sect.sct_oldown = own;
226         sect.sct_work = 100;
227         sect.sct_loyal = 0;
228     }
229     if (vtype == I_CIVIL && sect.sct_oldown != player->cnum) {
230         pr("Your civilians don't want to stay!\n");
231         getsect(start.sct_x, start.sct_y, &sect);
232         if (sect.sct_own != own) {
233             pr("Someone captured the sector you started from!\n");
234             pr("Your exploring people die of disappointment!\n");
235             sect.sct_flags &= ~MOVE_IN_PROGRESS;
236             putsect(&sect);
237             return RET_FAIL;
238         }
239     }
240     amt_dst = sect.sct_item[vtype];
241     if (amount > ITEM_MAX - amt_dst) {
242         amount = ITEM_MAX - amt_dst;
243         pr("Only %d can be left there.\n", amount);
244         if (amount <= 0)
245             getsect(start.sct_x, start.sct_y, &sect);
246     }
247     sect.sct_item[vtype] = amount + amt_dst;
248     /*
249      * Now add commodities to destination sector,
250      * along with plague that came along for the ride.
251      * Takeover unowned sectors if not deity.
252      */
253     if (!player->god && sect.sct_type != SCT_SANCT && justtook) {
254         pr("Sector %s is now yours.\n",
255            xyas(sect.sct_x, sect.sct_y, player->cnum));
256         if (opt_MOB_ACCESS) {
257             time(&sect.sct_access);
258             sect.sct_mobil = -(etu_per_update / sect_mob_neg_factor);
259         } else {
260             sect.sct_mobil = 0;
261         }
262     }
263     if (infected && sect.sct_pstage == PLG_HEALTHY)
264         sect.sct_pstage = PLG_EXPOSED;
265     if (vtype == I_CIVIL) {
266         sect.sct_loyal
267             = (amt_dst * sect.sct_loyal + amount * loyal) / (amt_dst + amount);
268         sect.sct_work
269             = (amt_dst * sect.sct_work + amount * work) / (amt_dst + amount);
270     }
271     putsect(&sect);
272     getsect(start.sct_x, start.sct_y, &start);
273     start.sct_flags &= ~MOVE_IN_PROGRESS;
274     putsect(&start);
275     return RET_OK;
276 }
277
278 /*ARGSUSED*/
279 static int
280 explore_map(s_char *what, coord curx, coord cury, s_char *arg)
281 {
282     struct nstr_sect ns;
283     struct natstr *np;
284     struct sctstr sect;
285     coord rel_x, rel_y;
286     s_char range[128];
287     s_char view[7];
288     int i;
289     int changed = 0;
290
291     np = getnatp(player->cnum);
292     rel_x = xrel(np, curx);
293     rel_y = yrel(np, cury);
294     sprintf(range, "%d:%d,%d:%d", rel_x - 2, rel_x + 2, rel_y - 1,
295             rel_y + 1);
296     if (!snxtsct(&ns, range))
297         return RET_FAIL;
298     i = 0;
299     while (i < 7 && nxtsct(&ns, &sect)) {
300         view[i] = dchr[sect.sct_type].d_mnem;
301         switch (sect.sct_type) {
302         case SCT_WATER:
303         case SCT_RURAL:
304         case SCT_MOUNT:
305         case SCT_WASTE:
306         case SCT_PLAINS:
307             break;
308         default:
309             if (sect.sct_own != player->cnum && !player->god)
310                 view[i] = '?';
311             break;
312         }
313         changed += map_set(player->cnum, ns.x, ns.y, view[i], 0);
314         i++;
315     }
316     if (changed)
317         writemap(player->cnum);
318     if (!getsect(curx, cury, &sect))
319         return RET_FAIL;
320     pr("    %c %c         min gold fert  oil uran\n", view[0], view[1]);
321     pr("   %c %c %c        %3d %4d %4d %4d %4d\n",
322        view[2], view[3], view[4],
323        sect.sct_min, sect.sct_gmin, sect.sct_fertil, sect.sct_oil,
324        sect.sct_uran);
325     pr("    %c %c\n", view[5], view[6]);
326     return RET_OK;
327 }