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:
49 static int cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg);
56 struct sctstr endsect;
79 istest = *player->argp[0] == 't';
80 if ((ip = whatitem(player->argp[1], "move what? ")) == 0)
83 if (!(p = getstarg(player->argp[2], "from sector : ", buf)))
85 if (!sarg_xy(p, &x, &y))
87 if (!getsect(x, y, §) || !player->owner) {
92 * military control necessary to move
93 * goodies in occupied territory.
95 if (!istest && sect.sct_oldown != player->cnum && vtype != I_MILIT) {
96 if (!military_control(§)) {
97 pr("Military control required to move goods.\n");
101 infected = sect.sct_pstage == PLG_INFECT;
102 amt_src = sect.sct_item[vtype];
103 if (!istest && amt_src <= 0) {
104 pr("No %s in %s\n", ip->i_name,
105 xyas(sect.sct_x, sect.sct_y, player->cnum));
109 mob = (int)sect.sct_mobil;
110 if (!istest && vtype == I_CIVIL && sect.sct_oldown != own) {
111 pr("You can't move conquered populace!\n");
115 pr("No mobility in %s\n",
116 xyas(sect.sct_x, sect.sct_y, player->cnum));
120 /* only used when moving civs; but prevent spurious compiler warnings */
121 work = sect.sct_work;
122 loyal = sect.sct_loyal;
123 if (vtype == I_CIVIL && work != 100)
124 pr("Warning: civil unrest\n");
127 sprintf(prompt, "Number of %s to test move? ", ip->i_name);
129 sprintf(prompt, "Number of %s to move? (max %d) ",
130 ip->i_name, amt_src);
131 if ((amount = onearg(player->argp[3], prompt)) < 0)
133 if (!check_sect_ok(§))
135 if (amount > amt_src) {
137 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);
140 pr("Only moving %d.\n", amount);
144 if (!istest && !want_to_abandon(§, vtype, amount, 0)) {
145 pr("Move cancelled.\n");
149 if (!check_sect_ok(§))
154 packing = sect.sct_effic >= 60 ? dchr[sect.sct_type].d_pkg : IPKG;
155 weight = (double)amount * ip->i_lbs / ip->i_pkg[packing];
157 * First remove commodities from source sector
160 getsect(x, y, &start);
161 if (start.sct_own != player->cnum) {
162 pr("Somebody has captured that sector!\n");
165 amt_src = start.sct_item[vtype];
166 if (amt_src < amount) {
167 pr("Only %d %s left in %s!\n", amt_src,
168 ip->i_name, 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 ? 0 : 1);
183 if (dam && !chance(weight / 200.0))
185 mcost = move_ground((s_char *)ip, §, &endsect,
186 weight, player->argp[4],
187 cmd_move_map, 0, &dam);
190 left = commdamage(amount, dam, ip->i_vtype);
193 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));
195 pr("All of the %s you were moving were destroyed!\n",
203 pr("Total movement cost = %d\n", mcost);
205 pr("No mobility used\n");
209 pr("Move aborted\n");
210 getsect(x, y, §);
211 sect.sct_mobil = (u_char)mob;
213 } else if (!istest) {
215 * decrement mobility appropriately.
217 getsect(x, y, &start);
218 mob = start.sct_mobil;
224 start.sct_mobil = (u_char)mob;
225 left = start.sct_mobil;
227 getsect(endsect.sct_x, endsect.sct_y, §);
231 * Check for lotsa stuff
233 if (sect.sct_own != player->cnum) {
234 if (sect.sct_own != 0)
235 pr("Somebody has captured that sector!\n");
236 getsect(x, y, §);
238 if (vtype == I_CIVIL && sect.sct_item[I_CIVIL]
239 && sect.sct_oldown != player->cnum) {
240 pr("Your civilians don't want to stay!\n");
241 getsect(x, y, §);
244 amt_dst = sect.sct_item[vtype];
245 if (amount > ITEM_MAX - amt_dst) {
246 pr("Only enough room for %d in %s. The goods will be returned.\n",
247 ITEM_MAX - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum));
248 /* FIXME Not nice. Move what we can and return the rest. */
249 getsect(x, y, §);
253 pr("%d mob left in %s\n", left,
254 xyas(start.sct_x, start.sct_y, player->cnum));
257 getsect(x, y, &start);
258 start.sct_flags &= ~MOVE_IN_PROGRESS;
263 /* If the sector that things are going to is no longer
264 owned by the player, and was the starting sector,
265 try to find somewhere to dump the stuff. If nowhere
266 to dump it, it disappears. */
267 if (sect.sct_own != player->cnum && sect.sct_x == x && sect.sct_y == y) {
268 pr("Can't return the goods, since the starting point is no longer\n");
269 pr("owned by you.\n");
270 /* First lets see if there is one with room */
271 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
272 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
273 if (tsct.sct_own != player->cnum)
275 amt_dst = tsct.sct_item[vtype];
276 if (amount > ITEM_MAX - amt_dst)
282 /* Find any sector if none with room */
283 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
284 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
285 if (tsct.sct_own != player->cnum)
291 pr("The goods had nowhere to go, and were destroyed.\n");
292 sect.sct_flags &= ~MOVE_IN_PROGRESS;
297 pr("The goods were dumped into %s.\n",
298 xyas(tsct.sct_x, tsct.sct_y, player->cnum));
299 getsect(tsct.sct_x, tsct.sct_y, §);
302 amt_dst = sect.sct_item[vtype];
303 if (amount > ITEM_MAX - amt_dst) {
304 amount = ITEM_MAX - amt_dst;
305 pr("Only room for %d, the rest were lost.\n", amount);
309 sect.sct_item[vtype] = amount + amt_dst;
311 * Now add commodities to destination sector,
312 * along with plague that came along for the ride.
313 * Takeover unowned sectors if not deity.
315 if (infected && sect.sct_pstage == PLG_HEALTHY)
316 sect.sct_pstage = PLG_EXPOSED;
317 if (vtype == I_CIVIL) {
319 = (amt_dst * sect.sct_loyal + amount * loyal) / (amt_dst + amount);
321 = (amt_dst * sect.sct_work + amount * work) / (amt_dst + amount);
324 getsect(x, y, &start);
325 start.sct_flags &= ~MOVE_IN_PROGRESS;
331 * Pretty tacky, but it works.
332 * If more commands start doing this, then
333 * rewrite map to do the right thing.
335 /* I think this is no longer used, check subs/move.c:move_ground() */
338 cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg)
340 player->argp[1] = arg;
341 player->argp[2] = "";
342 player->argp[3] = "";
343 player->argp[4] = "";
344 player->argp[5] = "";
350 want_to_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
354 /* First, would we be abandoning it? If not, just return that it's
356 if (!would_abandon(sp, vtype, amnt, lp))
359 sprintf(prompt, "Do you really want to abandon %s [yn]? ",
360 xyas(sp->sct_x, sp->sct_y, player->cnum));
362 /* now, if they say yes that it's ok, just return 1 */
371 would_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
373 int mil, civs, loyalcivs;
375 if ((vtype != I_CIVIL) && (vtype != I_MILIT))
378 mil = sp->sct_item[I_MILIT];
379 civs = sp->sct_item[I_CIVIL];
381 if (vtype == I_MILIT)
384 if (vtype == I_CIVIL)
387 if (sp->sct_own == sp->sct_oldown)
392 /* If they have a military unit there, they still own it */
394 && ((loyalcivs == 0) && (mil == 0)
395 && (has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp) == 0)))