2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2011, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure, Markus Armbruster
6 * Empire 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 3 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, see <http://www.gnu.org/licenses/>.
21 * See files README, COPYING and CREDITS in the root of the source
22 * tree for related information and legal notices. It is expected
23 * that future projects/authors will amend these files as needed.
27 * move.c: Move commodities around
29 * Known contributors to this file:
43 static int cmd_move_map(coord curx, coord cury, char *arg);
50 struct sctstr endsect;
73 istest = *player->argp[0] == 't';
74 if (!(ip = whatitem(player->argp[1], "move what? ")))
77 if (!(p = getstarg(player->argp[2], "from sector : ", buf)))
79 if (!sarg_xy(p, &x, &y))
81 if (!getsect(x, y, §) || !player->owner) {
86 * military control necessary to move
87 * goodies in occupied territory.
89 if (!istest && sect.sct_oldown != player->cnum && vtype != I_MILIT) {
90 if (!military_control(§)) {
91 pr("Military control required to move goods.\n");
95 infected = sect.sct_pstage == PLG_INFECT;
96 amt_src = sect.sct_item[vtype];
97 if (!istest && amt_src <= 0) {
98 pr("No %s in %s\n", ip->i_name,
99 xyas(sect.sct_x, sect.sct_y, player->cnum));
103 mob = sect.sct_mobil;
104 if (!istest && vtype == I_CIVIL && sect.sct_oldown != own) {
105 pr("You can't move conquered populace!\n");
109 pr("No mobility in %s\n",
110 xyas(sect.sct_x, sect.sct_y, player->cnum));
114 /* only used when moving civs; but prevent spurious compiler warnings */
115 work = sect.sct_work;
116 loyal = sect.sct_loyal;
117 if (vtype == I_CIVIL && work != 100)
118 pr("Warning: civil unrest\n");
121 sprintf(prompt, "Number of %s to test move? ", ip->i_name);
123 sprintf(prompt, "Number of %s to move? (max %d) ",
124 ip->i_name, amt_src);
125 if ((amount = onearg(player->argp[3], prompt)) < 0)
127 if (!check_sect_ok(§))
129 if (amount > amt_src) {
131 pr("Note: there are actually only %d %s in %s,\n"
132 "but the test will be made for %d %s as you requested.\n",
134 xyas(sect.sct_x, sect.sct_y, player->cnum),
138 pr("Only moving %d.\n", amount);
142 if (!istest && !want_to_abandon(§, vtype, amount, NULL)) {
143 pr("Move cancelled.\n");
147 if (!check_sect_ok(§))
152 packing = sect.sct_effic >= 60 ? dchr[sect.sct_type].d_pkg : IPKG;
153 weight = (double)amount * ip->i_lbs / ip->i_pkg[packing];
156 * First remove stuff 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",
168 xyas(start.sct_x, start.sct_y, player->cnum));
174 start.sct_item[vtype] = amt_src;
175 start.sct_flags |= MOVE_IN_PROGRESS;
180 * Now parse the path and return ending sector.
182 dam = !istest && !(opt_SUPER_BARS && vtype == I_BAR);
183 if (dam && !chance(weight / 200.0))
185 mcost = move_ground(§, &endsect, weight, player->argp[4],
186 cmd_move_map, 0, &dam);
189 left = commdamage(amount, dam, ip->i_uid);
192 pr("%d of the %s you were moving were destroyed!\n"
193 "Only %d %s made it to %s\n",
194 amount - left, ip->i_name, left, ip->i_name,
195 xyas(endsect.sct_x, endsect.sct_y, player->cnum));
197 pr("All of the %s you were moving were destroyed!\n",
205 pr("Total movement cost = %d\n", mcost);
207 pr("No mobility used\n");
211 pr("Move aborted\n");
212 getsect(x, y, §);
213 sect.sct_mobil = mob;
218 * Decrement mobility appropriately.
220 getsect(x, y, &start);
221 mob = start.sct_mobil;
227 start.sct_mobil = mob;
228 left = start.sct_mobil;
231 getsect(endsect.sct_x, endsect.sct_y, §);
235 * Check for lotsa stuff
237 if (sect.sct_own != player->cnum) {
238 if (sect.sct_own != 0)
239 pr("Somebody has captured that sector!\n");
240 getsect(x, y, §);
242 if (vtype == I_CIVIL && sect.sct_item[I_CIVIL]
243 && sect.sct_oldown != player->cnum) {
244 pr("Your civilians don't want to stay!\n");
245 getsect(x, y, §);
248 amt_dst = sect.sct_item[vtype];
249 if (amount > ITEM_MAX - amt_dst) {
250 pr("Only enough room for %d in %s. The goods will be returned.\n",
251 ITEM_MAX - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum));
252 /* FIXME Not nice. Move what we can and return the rest. */
253 getsect(x, y, §);
259 pr("%d mob left in %s\n", left,
260 xyas(start.sct_x, start.sct_y, player->cnum));
263 getsect(x, y, &start);
264 start.sct_flags &= ~MOVE_IN_PROGRESS;
270 * If the sector that things are going to is no longer owned by
271 * the player, and it was the starting sector, try to find
272 * somewhere to dump the stuff. If nowhere to dump it, it
275 if (sect.sct_own != player->cnum && sect.sct_x == x && sect.sct_y == y) {
276 pr("Can't return the goods, since the starting point is no longer\n");
277 pr("owned by you.\n");
278 /* First lets see if there is one with room */
279 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
280 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
281 if (tsct.sct_own != player->cnum)
283 amt_dst = tsct.sct_item[vtype];
284 if (amount > ITEM_MAX - amt_dst)
290 /* Find any sector if none with room */
291 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
292 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
293 if (tsct.sct_own != player->cnum)
299 pr("The goods had nowhere to go, and were destroyed.\n");
300 sect.sct_flags &= ~MOVE_IN_PROGRESS;
305 pr("The goods were dumped into %s.\n",
306 xyas(tsct.sct_x, tsct.sct_y, player->cnum));
307 getsect(tsct.sct_x, tsct.sct_y, §);
310 amt_dst = sect.sct_item[vtype];
311 if (amount > ITEM_MAX - amt_dst) {
312 amount = ITEM_MAX - amt_dst;
313 pr("Only room for %d, the rest were lost.\n", amount);
315 sect.sct_item[vtype] = amount + amt_dst;
317 * Now add commodities to destination sector,
318 * along with plague that came along for the ride.
319 * Takeover unowned sectors if not deity.
321 if (infected && sect.sct_pstage == PLG_HEALTHY)
322 sect.sct_pstage = PLG_EXPOSED;
323 if (vtype == I_CIVIL) {
325 = (amt_dst * sect.sct_loyal + amount * loyal) / (amt_dst + amount);
327 = (amt_dst * sect.sct_work + amount * work) / (amt_dst + amount);
330 getsect(x, y, &start);
331 start.sct_flags &= ~MOVE_IN_PROGRESS;
337 * Pretty tacky, but it works.
338 * If more commands start doing this, then
339 * rewrite map to do the right thing.
343 cmd_move_map(coord curx, coord cury, char *arg)
345 return display_region_map(0, EF_SHIP, curx, cury, arg);
349 want_to_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
354 * First, would we be abandoning it? If not, just return that
355 * it's ok to move out.
357 if (!would_abandon(sp, vtype, amnt, lp))
360 sprintf(prompt, "Do you really want to abandon %s [yn]? ",
361 xyas(sp->sct_x, sp->sct_y, player->cnum));
363 return askyn(prompt);
367 would_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
371 if (vtype != I_CIVIL && vtype != I_MILIT)
374 mil = sp->sct_item[I_MILIT];
375 civs = sp->sct_item[I_CIVIL];
377 if (vtype == I_MILIT)
379 if (vtype == I_CIVIL)
382 return sp->sct_own != 0 && civs <= 0 && mil <= 0
383 && !has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp);