2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2004, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
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.
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.
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
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.
28 * move.c: Move commodities around
30 * Known contributors to this file:
48 static int cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg);
55 struct sctstr endsect;
78 istest = *player->argp[0] == 't';
79 if ((ip = whatitem(player->argp[1], "move what? ")) == 0)
82 if (!(p = getstarg(player->argp[2], "from sector : ", buf)))
84 if (!sarg_xy(p, &x, &y))
86 if (!getsect(x, y, §) || !player->owner) {
91 * military control necessary to move
92 * goodies in occupied territory.
94 if (!istest && sect.sct_oldown != player->cnum && vtype != I_MILIT) {
95 if (!military_control(§)) {
96 pr("Military control required to move goods.\n");
100 infected = sect.sct_pstage == PLG_INFECT;
101 amt_src = sect.sct_item[vtype];
102 if (!istest && amt_src <= 0) {
103 pr("No %s in %s\n", ip->i_name,
104 xyas(sect.sct_x, sect.sct_y, player->cnum));
108 mob = (int)sect.sct_mobil;
109 if (!istest && vtype == I_CIVIL && sect.sct_oldown != own) {
110 pr("You can't move conquered populace!\n");
114 pr("No mobility in %s\n",
115 xyas(sect.sct_x, sect.sct_y, player->cnum));
119 /* only used when moving civs; but prevent spurious compiler warnings */
120 work = sect.sct_work;
121 loyal = sect.sct_loyal;
122 if (vtype == I_CIVIL && work != 100)
123 pr("Warning: civil unrest\n");
126 sprintf(prompt, "Number of %s to test move? ", ip->i_name);
128 sprintf(prompt, "Number of %s to move? (max %d) ",
129 ip->i_name, amt_src);
130 if ((amount = onearg(player->argp[3], prompt)) < 0)
132 if (!check_sect_ok(§))
134 if (amount > amt_src) {
136 pr("Note: there are actually only %d %s in %s,\nbut the test will be made for %d %s as you requested.\n", amt_src, ip->i_name, xyas(sect.sct_x, sect.sct_y, player->cnum), amount, ip->i_name);
139 pr("Only moving %d.\n", amount);
143 if (!istest && !want_to_abandon(§, vtype, amount, 0)) {
144 pr("Move cancelled.\n");
148 if (!check_sect_ok(§))
153 packing = sect.sct_effic >= 60 ? dchr[sect.sct_type].d_pkg : IPKG;
154 weight = (double)amount * ip->i_lbs / ip->i_pkg[packing];
156 * First remove commodities from source sector
159 getsect(x, y, &start);
160 if (start.sct_own != player->cnum) {
161 pr("Somebody has captured that sector!\n");
164 amt_src = start.sct_item[vtype];
165 if (amt_src < amount) {
166 pr("Only %d %s left in %s!\n", amt_src,
167 ip->i_name, xyas(start.sct_x, start.sct_y, player->cnum));
173 start.sct_item[vtype] = amt_src;
174 start.sct_flags |= MOVE_IN_PROGRESS;
179 * Now parse the path and return ending sector.
181 dam = (istest ? 0 : 1);
182 if (dam && !chance(weight / 200.0))
184 mcost = move_ground((s_char *)ip, §, &endsect,
185 weight, player->argp[4],
186 cmd_move_map, 0, &dam);
189 left = commdamage(amount, dam, ip->i_vtype);
192 pr("%d of the %s you were moving 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));
194 pr("All of the %s you were moving were destroyed!\n",
202 pr("Total movement cost = %d\n", mcost);
204 pr("No mobility used\n");
208 pr("Move aborted\n");
209 getsect(x, y, §);
210 sect.sct_mobil = (u_char)mob;
212 } else if (!istest) {
214 * decrement mobility appropriately.
216 getsect(x, y, &start);
217 mob = start.sct_mobil;
223 start.sct_mobil = (u_char)mob;
224 left = start.sct_mobil;
226 getsect(endsect.sct_x, endsect.sct_y, §);
230 * Check for lotsa stuff
232 if (sect.sct_own != player->cnum) {
233 if (sect.sct_own != 0)
234 pr("Somebody has captured that sector!\n");
235 getsect(x, y, §);
237 if (vtype == I_CIVIL && sect.sct_item[I_CIVIL]
238 && sect.sct_oldown != player->cnum) {
239 pr("Your civilians don't want to stay!\n");
240 getsect(x, y, §);
243 amt_dst = sect.sct_item[vtype];
244 if (amount > ITEM_MAX - amt_dst) {
245 pr("Only enough room for %d in %s. The goods will be returned.\n",
246 ITEM_MAX - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum));
247 /* FIXME Not nice. Move what we can and return the rest. */
248 getsect(x, y, §);
252 pr("%d mob left in %s\n", left,
253 xyas(start.sct_x, start.sct_y, player->cnum));
256 getsect(x, y, &start);
257 start.sct_flags &= ~MOVE_IN_PROGRESS;
262 /* If the sector that things are going to is no longer
263 owned by the player, and was the starting sector,
264 try to find somewhere to dump the stuff. If nowhere
265 to dump it, it disappears. */
266 if (sect.sct_own != player->cnum && sect.sct_x == x && sect.sct_y == y) {
267 pr("Can't return the goods, since the starting point is no longer\n");
268 pr("owned by you.\n");
269 /* First lets see if there is one with room */
270 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
271 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
272 if (tsct.sct_own != player->cnum)
274 amt_dst = tsct.sct_item[vtype];
275 if (amount > ITEM_MAX - amt_dst)
281 /* Find any sector if none with room */
282 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
283 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
284 if (tsct.sct_own != player->cnum)
290 pr("The goods had nowhere to go, and were destroyed.\n");
291 sect.sct_flags &= ~MOVE_IN_PROGRESS;
296 pr("The goods were dumped into %s.\n",
297 xyas(tsct.sct_x, tsct.sct_y, player->cnum));
298 getsect(tsct.sct_x, tsct.sct_y, §);
301 amt_dst = sect.sct_item[vtype];
302 if (amount > ITEM_MAX - amt_dst) {
303 amount = ITEM_MAX - amt_dst;
304 pr("Only room for %d, the rest were lost.\n", amount);
308 sect.sct_item[vtype] = amount + amt_dst;
310 * Now add commodities to destination sector,
311 * along with plague that came along for the ride.
312 * Takeover unowned sectors if not deity.
314 if (infected && sect.sct_pstage == PLG_HEALTHY)
315 sect.sct_pstage = PLG_EXPOSED;
316 if (vtype == I_CIVIL) {
318 = (amt_dst * sect.sct_loyal + amount * loyal) / (amt_dst + amount);
320 = (amt_dst * sect.sct_work + amount * work) / (amt_dst + amount);
323 getsect(x, y, &start);
324 start.sct_flags &= ~MOVE_IN_PROGRESS;
330 * Pretty tacky, but it works.
331 * If more commands start doing this, then
332 * rewrite map to do the right thing.
334 /* I think this is no longer used, check subs/move.c:move_ground() */
337 cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg)
339 player->argp[1] = arg;
340 player->argp[2] = "";
341 player->argp[3] = "";
342 player->argp[4] = "";
343 player->argp[5] = "";
349 want_to_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
353 /* First, would we be abandoning it? If not, just return that it's
355 if (!would_abandon(sp, vtype, amnt, lp))
358 sprintf(prompt, "Do you really want to abandon %s [yn]? ",
359 xyas(sp->sct_x, sp->sct_y, player->cnum));
361 /* now, if they say yes that it's ok, just return 1 */
370 would_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
372 int mil, civs, loyalcivs;
374 if ((vtype != I_CIVIL) && (vtype != I_MILIT))
377 mil = sp->sct_item[I_MILIT];
378 civs = sp->sct_item[I_CIVIL];
380 if (vtype == I_MILIT)
383 if (vtype == I_CIVIL)
386 if (sp->sct_own == sp->sct_oldown)
391 /* If they have a military unit there, they still own it */
393 && ((loyalcivs == 0) && (mil == 0)
394 && (has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp) == 0)))