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 ((getvar(V_MILIT, (s_char *)§, EF_SECTOR) + tot_mil) * 10
107 < getvar(V_CIVIL, (s_char *)§, EF_SECTOR)) {
108 pr("Military control required to move goods.\n");
112 stype = sect.sct_type;
114 infected = getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_INFECT;
115 amt_src = getvar(vtype, (s_char *)§, EF_SECTOR);
116 if (!istest && amt_src <= 0) {
117 pr("No %s in %s\n", ip->i_name,
118 xyas(sect.sct_x, sect.sct_y, player->cnum));
122 mob = (int)sect.sct_mobil;
123 if (!istest && vtype == V_CIVIL && sect.sct_oldown != own) {
124 pr("You can't move conquered populace!\n");
128 pr("No mobility in %s\n",
129 xyas(sect.sct_x, sect.sct_y, player->cnum));
132 if (vtype == V_CIVIL) {
133 work = sect.sct_work;
135 pr("Warning: civil unrest\n");
136 loyal = sect.sct_loyal;
137 } else if (vtype == V_MILIT) {
142 sprintf(prompt, "Number of %s to test move? ", ip->i_name);
144 sprintf(prompt, "Number of %s to move? (max %d) ",
145 ip->i_name, amt_src);
146 if ((amount = onearg(player->argp[3], prompt)) < 0)
148 if (!check_sect_ok(§))
150 if (amount > amt_src) {
152 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);
155 pr("Only moving %d.\n", amount);
159 if (!want_to_abandon(§, vtype, amount, 0)) {
160 pr("Move cancelled.\n");
164 if (!check_sect_ok(§))
169 packing = ip->i_pkg[dp->d_pkg];
170 if (packing > 1 && sect.sct_effic < 60)
172 weight = (double)amount *ip->i_lbs / packing;
174 * First remove commodities from source sector
177 getsect(x, y, &start);
178 if (start.sct_own != player->cnum) {
179 pr("Somebody has captured that sector!\n");
182 amt_src = getvar(vtype, (s_char *)&start, EF_SECTOR);
183 if (amt_src < amount) {
184 pr("Only %d %s left in %s!\n", amt_src,
185 ip->i_name, xyas(start.sct_x, start.sct_y, player->cnum));
191 putvar(vtype, amt_src, (s_char *)&start, EF_SECTOR);
192 start.sct_flags |= MOVE_IN_PROGRESS;
197 * Now parse the path and return ending sector.
199 dam = (istest ? 0 : 1);
200 if (dam && !chance(weight / 200.0))
202 mcost = move_ground((s_char *)ip, §, &endsect,
203 weight, player->argp[4],
204 cmd_move_map, 0, &dam);
207 left = commdamage(amount, dam, ip->i_vtype);
210 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));
212 pr("All of the %s you were moving were destroyed!\n",
220 pr("Total movement cost = %d\n", mcost);
222 pr("No mobility used\n");
226 pr("Move aborted\n");
227 getsect(x, y, §);
228 sect.sct_mobil = (u_char)mob;
230 } else if (!istest) {
232 * decrement mobility appropriately.
234 getsect(x, y, &start);
235 mob = start.sct_mobil;
241 start.sct_mobil = (u_char)mob;
242 left = start.sct_mobil;
244 getsect(endsect.sct_x, endsect.sct_y, §);
248 * Check for lotsa stuff
250 if (sect.sct_own != player->cnum) {
251 if (sect.sct_own != 0)
252 pr("Somebody has captured that sector!\n");
253 getsect(x, y, §);
255 if (vtype == V_CIVIL && getvar(V_CIVIL, (s_char *)§, EF_SECTOR) &&
256 sect.sct_oldown != player->cnum) {
257 pr("Your civilians don't want to stay!\n");
258 getsect(x, y, §);
261 amt_dst = getvar(vtype, (s_char *)§, EF_SECTOR);
262 if (32767 - amt_dst < amount) {
263 pr("Only enough room for %d in %s. The goods will be returned.\n",
264 32767 - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum));
265 getsect(x, y, §);
269 pr("%d mob left in %s\n", left,
270 xyas(start.sct_x, start.sct_y, player->cnum));
272 /* If the sector that things are going to is no longer
273 owned by the player, and was the starting sector,
274 try to find somewhere to dump the stuff. If nowhere
275 to dump it, it disappears. */
276 if (sect.sct_own != player->cnum && sect.sct_x == x && sect.sct_y == y) {
277 pr("Can't return the goods, since the starting point is no longer\n");
278 pr("owned by you.\n");
279 /* First lets see if there is one with room */
280 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
281 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
282 if (tsct.sct_own != player->cnum)
284 amt_dst = getvar(vtype, (s_char *)&tsct, EF_SECTOR);
285 if (32767 - amt_dst < amount)
291 /* Find any sector if none with room */
292 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
293 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
294 if (tsct.sct_own != player->cnum)
300 pr("The goods had nowhere to go, and were destroyed.\n");
301 sect.sct_flags &= ~MOVE_IN_PROGRESS;
306 pr("The goods were dumped into %s.\n",
307 xyas(tsct.sct_x, tsct.sct_y, player->cnum));
308 getsect(tsct.sct_x, tsct.sct_y, §);
311 amt_dst = getvar(vtype, (s_char *)§, EF_SECTOR);
312 if (32767 - amt_dst < amount) {
313 amount = 32767 - amt_dst;
314 pr("Only room for %d, the rest were lost.\n", amount);
318 if (putvar(vtype, amount + amt_dst, (s_char *)§, EF_SECTOR) < 0) {
319 pr("No more room in %s. The goods were lost.\n",
320 xyas(sect.sct_x, sect.sct_y, player->cnum));
321 /* charge the player mobility anyway */
325 * Now add commodities to destination sector,
326 * along with plague that came along for the ride.
327 * Takeover unowned sectors if not deity.
329 if (infected && getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == 0)
330 putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)§, EF_SECTOR);
331 if (vtype == V_CIVIL) {
333 sect.sct_loyal = ((amt_dst * sect.sct_loyal) +
334 (amount * loyal)) / (amt_dst + amount);
335 sect.sct_work = ((amt_dst * sect.sct_work) +
336 (amount * work)) / (amt_dst + amount);
337 } else { /* ! NEW_WORK */
339 /* It only takes one bad apple... */
340 if (sect.sct_loyal < loyal)
341 sect.sct_loyal = loyal;
342 if (sect.sct_work > work)
343 sect.sct_work = work;
347 getsect(x, y, &start);
348 start.sct_flags &= ~MOVE_IN_PROGRESS;
354 * Pretty tacky, but it works.
355 * If more commands start doing this, then
356 * rewrite map to do the right thing.
358 /* I think this is no longer used, check subs/move.c:move_ground() */
361 cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg)
363 player->argp[1] = arg;
364 player->argp[2] = "";
365 player->argp[3] = "";
366 player->argp[4] = "";
367 player->argp[5] = "";
373 want_to_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
377 /* First, would we be abandoning it? If not, just return that it's
379 if (!would_abandon(sp, vtype, amnt, lp))
382 sprintf(prompt, "Do you really want to abandon %s [yn]? ",
383 xyas(sp->sct_x, sp->sct_y, player->cnum));
385 /* now, if they say yes that it's ok, just return 1 */
394 would_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
396 int mil, civs, loyalcivs;
398 if ((vtype != V_CIVIL) && (vtype != V_MILIT))
401 mil = getvar(V_MILIT, (s_char *)sp, EF_SECTOR);
402 civs = getvar(V_CIVIL, (s_char *)sp, EF_SECTOR);
404 if (vtype == V_MILIT)
407 if (vtype == V_CIVIL)
410 if (sp->sct_own == sp->sct_oldown)
415 /* If they have a military unit there, they still own it */
417 && ((loyalcivs == 0) && (mil == 0)
418 && (has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp) == 0)))