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:
50 static int cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg);
57 struct sctstr endsect;
82 istest = *player->argp[0] == 't';
83 if ((ip = whatitem(player->argp[1], "move what? ")) == 0)
86 if (!(p = getstarg(player->argp[2], "from sector : ", buf)))
88 if (!sarg_xy(p, &x, &y))
90 if (!getsect(x, y, §) || !player->owner) {
95 * military control necessary to move
96 * goodies in occupied territory.
98 if (!istest && sect.sct_oldown != player->cnum && vtype != V_MILIT) {
102 snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y);
103 while (nxtitem(&ni, (s_char *)&land)) {
104 if (land.lnd_own == player->cnum)
105 tot_mil += total_mil(&land);
107 if ((getvar(V_MILIT, (s_char *)§, EF_SECTOR) + tot_mil) * 10
108 < getvar(V_CIVIL, (s_char *)§, EF_SECTOR)) {
109 pr("Military control required to move goods.\n");
113 stype = sect.sct_type;
115 infected = getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_INFECT;
116 amt_src = getvar(vtype, (s_char *)§, EF_SECTOR);
117 if (!istest && amt_src <= 0) {
118 pr("No %s in %s\n", ip->i_name,
119 xyas(sect.sct_x, sect.sct_y, player->cnum));
123 mob = (int)sect.sct_mobil;
124 if (!istest && vtype == V_CIVIL && sect.sct_oldown != own) {
125 pr("You can't move conquered populace!\n");
129 pr("No mobility in %s\n",
130 xyas(sect.sct_x, sect.sct_y, player->cnum));
133 if (vtype == V_CIVIL) {
134 work = sect.sct_work;
136 pr("Warning: civil unrest\n");
137 loyal = sect.sct_loyal;
138 } else if (vtype == V_MILIT) {
143 sprintf(prompt, "Number of %s to test move? ", ip->i_name);
145 sprintf(prompt, "Number of %s to move? (max %d) ",
146 ip->i_name, amt_src);
147 if ((amount = onearg(player->argp[3], prompt)) < 0)
149 if (!check_sect_ok(§))
151 if (amount > amt_src) {
153 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);
156 pr("Only moving %d.\n", amount);
160 if (!want_to_abandon(§, vtype, amount, 0)) {
161 pr("Move cancelled.\n");
165 if (!check_sect_ok(§))
170 packing = ip->i_pkg[dp->d_pkg];
171 if (packing > 1 && sect.sct_effic < 60)
173 weight = (double)amount *ip->i_lbs / packing;
175 * First remove commodities from source sector
178 getsect(x, y, &start);
179 if (start.sct_own != player->cnum) {
180 pr("Somebody has captured that sector!\n");
183 amt_src = getvar(vtype, (s_char *)&start, EF_SECTOR);
184 if (amt_src < amount) {
185 pr("Only %d %s left in %s!\n", amt_src,
186 ip->i_name, xyas(start.sct_x, start.sct_y, player->cnum));
192 putvar(vtype, amt_src, (s_char *)&start, EF_SECTOR);
193 start.sct_flags |= MOVE_IN_PROGRESS;
198 * Now parse the path and return ending sector.
200 dam = (istest ? 0 : 1);
201 if (dam && !chance(weight / 200.0))
203 mcost = move_ground((s_char *)ip, §, &endsect,
204 (double)sect.sct_mobil, weight, player->argp[4],
205 cmd_move_map, 0, &dam);
208 left = commdamage(amount, dam, ip->i_vtype);
211 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));
213 pr("All of the %s you were moving were destroyed!\n",
221 pr("Total movement cost = %d\n", mcost);
223 pr("No mobility used\n");
227 pr("Move aborted\n");
228 getsect(x, y, §);
229 sect.sct_mobil = (u_char)mob;
231 } else if (!istest) {
233 * decrement mobility appropriately.
235 getsect(x, y, &start);
236 mob = start.sct_mobil;
242 start.sct_mobil = (u_char)mob;
243 left = start.sct_mobil;
245 getsect(endsect.sct_x, endsect.sct_y, §);
249 * Check for lotsa stuff
251 if (sect.sct_own != player->cnum) {
252 if (sect.sct_own != 0)
253 pr("Somebody has captured that sector!\n");
254 getsect(x, y, §);
256 if (vtype == V_CIVIL && getvar(V_CIVIL, (s_char *)§, EF_SECTOR) &&
257 sect.sct_oldown != player->cnum) {
258 pr("Your civilians don't want to stay!\n");
259 getsect(x, y, §);
262 amt_dst = getvar(vtype, (s_char *)§, EF_SECTOR);
263 if (32767 - amt_dst < amount) {
264 pr("Only enough room for %d in %s. The goods will be returned.\n",
265 32767 - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum));
266 getsect(x, y, §);
270 pr("%d mob left in %s\n", left,
271 xyas(start.sct_x, start.sct_y, player->cnum));
273 /* If the sector that things are going to is no longer
274 owned by the player, and was the starting sector,
275 try to find somewhere to dump the stuff. If nowhere
276 to dump it, it disappears. */
277 if (sect.sct_own != player->cnum && sect.sct_x == x && sect.sct_y == y) {
278 pr("Can't return the goods, since the starting point is no longer\n");
279 pr("owned by you.\n");
280 /* First lets see if there is one with room */
281 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
282 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
283 if (tsct.sct_own != player->cnum)
285 amt_dst = getvar(vtype, (s_char *)&tsct, EF_SECTOR);
286 if (32767 - amt_dst < amount)
292 /* Find any sector if none with room */
293 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
294 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
295 if (tsct.sct_own != player->cnum)
301 pr("The goods had nowhere to go, and were destroyed.\n");
302 sect.sct_flags &= ~MOVE_IN_PROGRESS;
307 pr("The goods were dumped into %s.\n",
308 xyas(tsct.sct_x, tsct.sct_y, player->cnum));
309 getsect(tsct.sct_x, tsct.sct_y, §);
312 amt_dst = getvar(vtype, (s_char *)§, EF_SECTOR);
313 if (32767 - amt_dst < amount) {
314 amount = 32767 - amt_dst;
315 pr("Only room for %d, the rest were lost.\n", amount);
319 if (putvar(vtype, amount + amt_dst, (s_char *)§, EF_SECTOR) < 0) {
320 pr("No more room in %s. The goods were lost.\n",
321 xyas(sect.sct_x, sect.sct_y, player->cnum));
322 /* charge the player mobility anyway */
326 * Now add commodities to destination sector,
327 * along with plague that came along for the ride.
328 * Takeover unowned sectors if not deity.
330 if (infected && getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == 0)
331 putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)§, EF_SECTOR);
332 if (vtype == V_CIVIL) {
334 sect.sct_loyal = ((amt_dst * sect.sct_loyal) +
335 (amount * loyal)) / (amt_dst + amount);
336 sect.sct_work = ((amt_dst * sect.sct_work) +
337 (amount * work)) / (amt_dst + amount);
338 } else { /* ! NEW_WORK */
340 /* It only takes one bad apple... */
341 if (sect.sct_loyal < loyal)
342 sect.sct_loyal = loyal;
343 if (sect.sct_work > work)
344 sect.sct_work = work;
348 getsect(x, y, &start);
349 start.sct_flags &= ~MOVE_IN_PROGRESS;
355 * Pretty tacky, but it works.
356 * If more commands start doing this, then
357 * rewrite map to do the right thing.
359 /* I think this is no longer used, check subs/move.c:move_ground() */
362 cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg)
364 player->argp[1] = arg;
365 player->argp[2] = "";
366 player->argp[3] = "";
367 player->argp[4] = "";
368 player->argp[5] = "";
374 want_to_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
378 /* First, would we be abandoning it? If not, just return that it's
380 if (!would_abandon(sp, vtype, amnt, lp))
383 sprintf(prompt, "Do you really want to abandon %s [yn]? ",
384 xyas(sp->sct_x, sp->sct_y, player->cnum));
386 /* now, if they say yes that it's ok, just return 1 */
395 would_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
398 int mil, civs, loyalcivs;
400 if ((vtype != V_CIVIL) && (vtype != V_MILIT))
403 bcopy((s_char *)sp, (s_char *)§, sizeof(struct sctstr));
405 mil = getvar(V_MILIT, (s_char *)sp, EF_SECTOR);
406 civs = getvar(V_CIVIL, (s_char *)sp, EF_SECTOR);
408 if (vtype == V_MILIT)
411 if (vtype == V_CIVIL)
414 if (sp->sct_own == sp->sct_oldown)
419 /* If they have a military unit there, they still own it */
420 if (sp->sct_own != 0 && ((loyalcivs == 0) && (mil == 0) &&
422 (sp->sct_x, sp->sct_y, sp->sct_own,