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 != V_MILIT) {
101 snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y);
102 while (nxtitem(&ni, (s_char *)&land)) {
103 if (land.lnd_own == player->cnum)
104 tot_mil += total_mil(&land);
106 if ((sect.sct_item[I_MILIT] + tot_mil) * 10 < sect.sct_item[I_CIVIL]) {
107 pr("Military control required to move goods.\n");
111 stype = sect.sct_type;
113 infected = sect.sct_pstage == PLG_INFECT;
114 amt_src = sect.sct_item[vtype];
115 if (!istest && amt_src <= 0) {
116 pr("No %s in %s\n", ip->i_name,
117 xyas(sect.sct_x, sect.sct_y, player->cnum));
121 mob = (int)sect.sct_mobil;
122 if (!istest && vtype == V_CIVIL && sect.sct_oldown != own) {
123 pr("You can't move conquered populace!\n");
127 pr("No mobility in %s\n",
128 xyas(sect.sct_x, sect.sct_y, player->cnum));
131 if (vtype == V_CIVIL) {
132 work = sect.sct_work;
134 pr("Warning: civil unrest\n");
135 loyal = sect.sct_loyal;
136 } else if (vtype == V_MILIT) {
141 sprintf(prompt, "Number of %s to test move? ", ip->i_name);
143 sprintf(prompt, "Number of %s to move? (max %d) ",
144 ip->i_name, amt_src);
145 if ((amount = onearg(player->argp[3], prompt)) < 0)
147 if (!check_sect_ok(§))
149 if (amount > amt_src) {
151 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);
154 pr("Only moving %d.\n", amount);
158 if (!istest && !want_to_abandon(§, vtype, amount, 0)) {
159 pr("Move cancelled.\n");
163 if (!check_sect_ok(§))
168 packing = ip->i_pkg[dp->d_pkg];
169 if (packing > 1 && sect.sct_effic < 60)
171 weight = (double)amount *ip->i_lbs / packing;
173 * First remove commodities from source sector
176 getsect(x, y, &start);
177 if (start.sct_own != player->cnum) {
178 pr("Somebody has captured that sector!\n");
181 amt_src = start.sct_item[vtype];
182 if (amt_src < amount) {
183 pr("Only %d %s left in %s!\n", amt_src,
184 ip->i_name, xyas(start.sct_x, start.sct_y, player->cnum));
190 start.sct_item[vtype] = amt_src;
191 start.sct_flags |= MOVE_IN_PROGRESS;
196 * Now parse the path and return ending sector.
198 dam = (istest ? 0 : 1);
199 if (dam && !chance(weight / 200.0))
201 mcost = move_ground((s_char *)ip, §, &endsect,
202 weight, player->argp[4],
203 cmd_move_map, 0, &dam);
206 left = commdamage(amount, dam, ip->i_vtype);
209 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));
211 pr("All of the %s you were moving were destroyed!\n",
219 pr("Total movement cost = %d\n", mcost);
221 pr("No mobility used\n");
225 pr("Move aborted\n");
226 getsect(x, y, §);
227 sect.sct_mobil = (u_char)mob;
229 } else if (!istest) {
231 * decrement mobility appropriately.
233 getsect(x, y, &start);
234 mob = start.sct_mobil;
240 start.sct_mobil = (u_char)mob;
241 left = start.sct_mobil;
243 getsect(endsect.sct_x, endsect.sct_y, §);
247 * Check for lotsa stuff
249 if (sect.sct_own != player->cnum) {
250 if (sect.sct_own != 0)
251 pr("Somebody has captured that sector!\n");
252 getsect(x, y, §);
254 if (vtype == V_CIVIL && sect.sct_item[I_CIVIL]
255 && sect.sct_oldown != player->cnum) {
256 pr("Your civilians don't want to stay!\n");
257 getsect(x, y, §);
260 amt_dst = sect.sct_item[vtype];
261 if (amount > ITEM_MAX - amt_dst) {
262 pr("Only enough room for %d in %s. The goods will be returned.\n",
263 ITEM_MAX - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum));
264 /* FIXME Not nice. Move what we can and return the rest. */
265 getsect(x, y, §);
269 pr("%d mob left in %s\n", left,
270 xyas(start.sct_x, start.sct_y, player->cnum));
273 getsect(x, y, &start);
274 start.sct_flags &= ~MOVE_IN_PROGRESS;
279 /* If the sector that things are going to is no longer
280 owned by the player, and was the starting sector,
281 try to find somewhere to dump the stuff. If nowhere
282 to dump it, it disappears. */
283 if (sect.sct_own != player->cnum && sect.sct_x == x && sect.sct_y == y) {
284 pr("Can't return the goods, since the starting point is no longer\n");
285 pr("owned by you.\n");
286 /* First lets see if there is one with room */
287 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
288 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
289 if (tsct.sct_own != player->cnum)
291 amt_dst = tsct.sct_item[vtype];
292 if (amount > ITEM_MAX - amt_dst)
298 /* Find any sector if none with room */
299 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
300 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
301 if (tsct.sct_own != player->cnum)
307 pr("The goods had nowhere to go, and were destroyed.\n");
308 sect.sct_flags &= ~MOVE_IN_PROGRESS;
313 pr("The goods were dumped into %s.\n",
314 xyas(tsct.sct_x, tsct.sct_y, player->cnum));
315 getsect(tsct.sct_x, tsct.sct_y, §);
318 amt_dst = sect.sct_item[vtype];
319 if (amount > ITEM_MAX - amt_dst) {
320 amount = ITEM_MAX - amt_dst;
321 pr("Only room for %d, the rest were lost.\n", amount);
325 sect.sct_item[vtype] = amount + amt_dst;
327 * Now add commodities to destination sector,
328 * along with plague that came along for the ride.
329 * Takeover unowned sectors if not deity.
331 if (infected && sect.sct_pstage == PLG_HEALTHY)
332 sect.sct_pstage = PLG_EXPOSED;
333 if (vtype == V_CIVIL) {
335 = (amt_dst * sect.sct_loyal + amount * loyal) / (amt_dst + amount);
337 = (amt_dst * sect.sct_work + amount * work) / (amt_dst + amount);
340 getsect(x, y, &start);
341 start.sct_flags &= ~MOVE_IN_PROGRESS;
347 * Pretty tacky, but it works.
348 * If more commands start doing this, then
349 * rewrite map to do the right thing.
351 /* I think this is no longer used, check subs/move.c:move_ground() */
354 cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg)
356 player->argp[1] = arg;
357 player->argp[2] = "";
358 player->argp[3] = "";
359 player->argp[4] = "";
360 player->argp[5] = "";
366 want_to_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
370 /* First, would we be abandoning it? If not, just return that it's
372 if (!would_abandon(sp, vtype, amnt, lp))
375 sprintf(prompt, "Do you really want to abandon %s [yn]? ",
376 xyas(sp->sct_x, sp->sct_y, player->cnum));
378 /* now, if they say yes that it's ok, just return 1 */
387 would_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
389 int mil, civs, loyalcivs;
391 if ((vtype != V_CIVIL) && (vtype != V_MILIT))
394 mil = sp->sct_item[I_MILIT];
395 civs = sp->sct_item[I_CIVIL];
397 if (vtype == V_MILIT)
400 if (vtype == V_CIVIL)
403 if (sp->sct_own == sp->sct_oldown)
408 /* If they have a military unit there, they still own it */
410 && ((loyalcivs == 0) && (mil == 0)
411 && (has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp) == 0)))