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
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 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.
28 * move.c: Move commodities around
30 * Known contributors to this file:
50 static int cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg);
57 struct sctstr endsect;
80 istest = *player->argp[0] == 't';
81 if ((ip = whatitem(player->argp[1], "move what? ")) == 0)
84 if (!(p = getstarg(player->argp[2], "from sector : ", buf)))
86 if (!sarg_xy(p, &x, &y))
88 if (!getsect(x, y, §) || !player->owner) {
93 * military control necessary to move
94 * goodies in occupied territory.
96 if (!istest && sect.sct_oldown != player->cnum && vtype != I_MILIT) {
97 if (!military_control(§)) {
98 pr("Military control required to move goods.\n");
102 infected = sect.sct_pstage == PLG_INFECT;
103 amt_src = sect.sct_item[vtype];
104 if (!istest && amt_src <= 0) {
105 pr("No %s in %s\n", ip->i_name,
106 xyas(sect.sct_x, sect.sct_y, player->cnum));
110 mob = (int)sect.sct_mobil;
111 if (!istest && vtype == I_CIVIL && sect.sct_oldown != own) {
112 pr("You can't move conquered populace!\n");
116 pr("No mobility in %s\n",
117 xyas(sect.sct_x, sect.sct_y, player->cnum));
121 /* only used when moving civs; but prevent spurious compiler warnings */
122 work = sect.sct_work;
123 loyal = sect.sct_loyal;
124 if (vtype == I_CIVIL && work != 100)
125 pr("Warning: civil unrest\n");
128 sprintf(prompt, "Number of %s to test move? ", ip->i_name);
130 sprintf(prompt, "Number of %s to move? (max %d) ",
131 ip->i_name, amt_src);
132 if ((amount = onearg(player->argp[3], prompt)) < 0)
134 if (!check_sect_ok(§))
136 if (amount > amt_src) {
138 pr("Note: there are actually only %d %s in %s,\n"
139 "but the test will be made for %d %s as you requested.\n",
141 xyas(sect.sct_x, sect.sct_y, player->cnum),
145 pr("Only moving %d.\n", amount);
149 if (!istest && !want_to_abandon(§, vtype, amount, 0)) {
150 pr("Move cancelled.\n");
154 if (!check_sect_ok(§))
159 packing = sect.sct_effic >= 60 ? dchr[sect.sct_type].d_pkg : IPKG;
160 weight = (double)amount * ip->i_lbs / ip->i_pkg[packing];
163 * First remove stuff from source sector
166 getsect(x, y, &start);
167 if (start.sct_own != player->cnum) {
168 pr("Somebody has captured that sector!\n");
171 amt_src = start.sct_item[vtype];
172 if (amt_src < amount) {
173 pr("Only %d %s left in %s!\n", amt_src,
174 ip->i_name, xyas(start.sct_x, start.sct_y, player->cnum));
180 start.sct_item[vtype] = amt_src;
181 start.sct_flags |= MOVE_IN_PROGRESS;
186 * Now parse the path and return ending sector.
188 dam = (istest ? 0 : 1);
189 if (dam && !chance(weight / 200.0))
191 mcost = move_ground((s_char *)ip, §, &endsect,
192 weight, player->argp[4],
193 cmd_move_map, 0, &dam);
196 left = commdamage(amount, dam, ip->i_vtype);
199 pr("%d of the %s you were moving were destroyed!\n"
200 "Only %d %s made it to %s\n",
201 amount - left, ip->i_name, left, ip->i_name,
202 xyas(endsect.sct_x, endsect.sct_y, player->cnum));
204 pr("All of the %s you were moving were destroyed!\n",
212 pr("Total movement cost = %d\n", mcost);
214 pr("No mobility used\n");
218 pr("Move aborted\n");
219 getsect(x, y, §);
220 sect.sct_mobil = (u_char)mob;
225 * Decrement mobility appropriately.
227 getsect(x, y, &start);
228 mob = start.sct_mobil;
234 start.sct_mobil = (u_char)mob;
235 left = start.sct_mobil;
238 getsect(endsect.sct_x, endsect.sct_y, §);
242 * Check for lotsa stuff
244 if (sect.sct_own != player->cnum) {
245 if (sect.sct_own != 0)
246 pr("Somebody has captured that sector!\n");
247 getsect(x, y, §);
249 if (vtype == I_CIVIL && sect.sct_item[I_CIVIL]
250 && sect.sct_oldown != player->cnum) {
251 pr("Your civilians don't want to stay!\n");
252 getsect(x, y, §);
255 amt_dst = sect.sct_item[vtype];
256 if (amount > ITEM_MAX - amt_dst) {
257 pr("Only enough room for %d in %s. The goods will be returned.\n",
258 ITEM_MAX - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum));
259 /* FIXME Not nice. Move what we can and return the rest. */
260 getsect(x, y, §);
266 pr("%d mob left in %s\n", left,
267 xyas(start.sct_x, start.sct_y, player->cnum));
270 getsect(x, y, &start);
271 start.sct_flags &= ~MOVE_IN_PROGRESS;
277 * If the sector that things are going to is no longer owned by
278 * the player, and it was the starting sector, try to find
279 * somewhere to dump the stuff. If nowhere to dump it, it
282 if (sect.sct_own != player->cnum && sect.sct_x == x && sect.sct_y == y) {
283 pr("Can't return the goods, since the starting point is no longer\n");
284 pr("owned by you.\n");
285 /* First lets see if there is one with room */
286 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
287 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
288 if (tsct.sct_own != player->cnum)
290 amt_dst = tsct.sct_item[vtype];
291 if (amount > ITEM_MAX - amt_dst)
297 /* Find any sector if none with room */
298 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
299 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
300 if (tsct.sct_own != player->cnum)
306 pr("The goods had nowhere to go, and were destroyed.\n");
307 sect.sct_flags &= ~MOVE_IN_PROGRESS;
312 pr("The goods were dumped into %s.\n",
313 xyas(tsct.sct_x, tsct.sct_y, player->cnum));
314 getsect(tsct.sct_x, tsct.sct_y, §);
317 amt_dst = sect.sct_item[vtype];
318 if (amount > ITEM_MAX - amt_dst) {
319 amount = ITEM_MAX - amt_dst;
320 pr("Only room for %d, the rest were lost.\n", amount);
322 sect.sct_item[vtype] = amount + amt_dst;
324 * Now add commodities to destination sector,
325 * along with plague that came along for the ride.
326 * Takeover unowned sectors if not deity.
328 if (infected && sect.sct_pstage == PLG_HEALTHY)
329 sect.sct_pstage = PLG_EXPOSED;
330 if (vtype == I_CIVIL) {
332 = (amt_dst * sect.sct_loyal + amount * loyal) / (amt_dst + amount);
334 = (amt_dst * sect.sct_work + amount * work) / (amt_dst + amount);
337 getsect(x, y, &start);
338 start.sct_flags &= ~MOVE_IN_PROGRESS;
344 * Pretty tacky, but it works.
345 * If more commands start doing this, then
346 * rewrite map to do the right thing.
348 /* I think this is no longer used, check subs/move.c:move_ground() */
351 cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg)
353 player->argp[1] = arg;
354 player->argp[2] = "";
355 player->argp[3] = "";
356 player->argp[4] = "";
357 player->argp[5] = "";
363 want_to_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
368 * First, would we be abandoning it? If not, just return that
369 * it's ok to move out.
371 if (!would_abandon(sp, vtype, amnt, lp))
374 sprintf(prompt, "Do you really want to abandon %s [yn]? ",
375 xyas(sp->sct_x, sp->sct_y, player->cnum));
377 return askyn(prompt);
381 would_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
383 int mil, civs, loyalcivs;
385 if ((vtype != I_CIVIL) && (vtype != I_MILIT))
388 mil = sp->sct_item[I_MILIT];
389 civs = sp->sct_item[I_CIVIL];
391 if (vtype == I_MILIT)
394 if (vtype == I_CIVIL)
397 if (sp->sct_own == sp->sct_oldown)
402 /* If they have a military unit there, they still own it */
404 && ((loyalcivs == 0) && (mil == 0)
405 && (has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp) == 0)))