2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2000, 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;
81 istest = *player->argp[0] == 't';
82 if ((ip = whatitem(player->argp[1], "move what? ")) == 0)
85 if (!(p = getstarg(player->argp[2], "from sector : ", buf)))
87 if (!sarg_xy(p, &x, &y))
89 if (!getsect(x, y, §) || !player->owner) {
94 * military control necessary to move
95 * goodies in occupied territory.
97 if (!istest && sect.sct_oldown != player->cnum && vtype != I_MILIT) {
98 if (!military_control(§)) {
99 pr("Military control required to move goods.\n");
103 stype = sect.sct_type;
105 infected = sect.sct_pstage == PLG_INFECT;
106 amt_src = sect.sct_item[vtype];
107 if (!istest && amt_src <= 0) {
108 pr("No %s in %s\n", ip->i_name,
109 xyas(sect.sct_x, sect.sct_y, player->cnum));
113 mob = (int)sect.sct_mobil;
114 if (!istest && vtype == I_CIVIL && sect.sct_oldown != own) {
115 pr("You can't move conquered populace!\n");
119 pr("No mobility in %s\n",
120 xyas(sect.sct_x, sect.sct_y, player->cnum));
124 /* only used when moving civs; but prevent spurious compiler warnings */
125 work = sect.sct_work;
126 loyal = sect.sct_loyal;
127 if (vtype == I_CIVIL && work != 100)
128 pr("Warning: civil unrest\n");
131 sprintf(prompt, "Number of %s to test move? ", ip->i_name);
133 sprintf(prompt, "Number of %s to move? (max %d) ",
134 ip->i_name, amt_src);
135 if ((amount = onearg(player->argp[3], prompt)) < 0)
137 if (!check_sect_ok(§))
139 if (amount > amt_src) {
141 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);
144 pr("Only moving %d.\n", amount);
148 if (!istest && !want_to_abandon(§, vtype, amount, 0)) {
149 pr("Move cancelled.\n");
153 if (!check_sect_ok(§))
158 packing = ip->i_pkg[dp->d_pkg];
159 if (packing > 1 && sect.sct_effic < 60)
161 weight = (double)amount *ip->i_lbs / packing;
163 * First remove commodities 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!\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));
201 pr("All of the %s you were moving were destroyed!\n",
209 pr("Total movement cost = %d\n", mcost);
211 pr("No mobility used\n");
215 pr("Move aborted\n");
216 getsect(x, y, §);
217 sect.sct_mobil = (u_char)mob;
219 } else if (!istest) {
221 * decrement mobility appropriately.
223 getsect(x, y, &start);
224 mob = start.sct_mobil;
230 start.sct_mobil = (u_char)mob;
231 left = start.sct_mobil;
233 getsect(endsect.sct_x, endsect.sct_y, §);
237 * Check for lotsa stuff
239 if (sect.sct_own != player->cnum) {
240 if (sect.sct_own != 0)
241 pr("Somebody has captured that sector!\n");
242 getsect(x, y, §);
244 if (vtype == I_CIVIL && sect.sct_item[I_CIVIL]
245 && sect.sct_oldown != player->cnum) {
246 pr("Your civilians don't want to stay!\n");
247 getsect(x, y, §);
250 amt_dst = sect.sct_item[vtype];
251 if (amount > ITEM_MAX - amt_dst) {
252 pr("Only enough room for %d in %s. The goods will be returned.\n",
253 ITEM_MAX - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum));
254 /* FIXME Not nice. Move what we can and return the rest. */
255 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;
269 /* If the sector that things are going to is no longer
270 owned by the player, and was the starting sector,
271 try to find somewhere to dump the stuff. If nowhere
272 to dump it, it disappears. */
273 if (sect.sct_own != player->cnum && sect.sct_x == x && sect.sct_y == y) {
274 pr("Can't return the goods, since the starting point is no longer\n");
275 pr("owned by you.\n");
276 /* First lets see if there is one with room */
277 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
278 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
279 if (tsct.sct_own != player->cnum)
281 amt_dst = tsct.sct_item[vtype];
282 if (amount > ITEM_MAX - amt_dst)
288 /* Find any sector if none with room */
289 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
290 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
291 if (tsct.sct_own != player->cnum)
297 pr("The goods had nowhere to go, and were destroyed.\n");
298 sect.sct_flags &= ~MOVE_IN_PROGRESS;
303 pr("The goods were dumped into %s.\n",
304 xyas(tsct.sct_x, tsct.sct_y, player->cnum));
305 getsect(tsct.sct_x, tsct.sct_y, §);
308 amt_dst = sect.sct_item[vtype];
309 if (amount > ITEM_MAX - amt_dst) {
310 amount = ITEM_MAX - amt_dst;
311 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.
341 /* I think this is no longer used, check subs/move.c:move_ground() */
344 cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg)
346 player->argp[1] = arg;
347 player->argp[2] = "";
348 player->argp[3] = "";
349 player->argp[4] = "";
350 player->argp[5] = "";
356 want_to_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
360 /* First, would we be abandoning it? If not, just return that it's
362 if (!would_abandon(sp, vtype, amnt, lp))
365 sprintf(prompt, "Do you really want to abandon %s [yn]? ",
366 xyas(sp->sct_x, sp->sct_y, player->cnum));
368 /* now, if they say yes that it's ok, just return 1 */
377 would_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
379 int mil, civs, loyalcivs;
381 if ((vtype != I_CIVIL) && (vtype != I_MILIT))
384 mil = sp->sct_item[I_MILIT];
385 civs = sp->sct_item[I_CIVIL];
387 if (vtype == I_MILIT)
390 if (vtype == I_CIVIL)
393 if (sp->sct_own == sp->sct_oldown)
398 /* If they have a military unit there, they still own it */
400 && ((loyalcivs == 0) && (mil == 0)
401 && (has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp) == 0)))