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.
99 sect.sct_oldown != player->cnum &&
104 snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y);
105 while (nxtitem(&ni, (s_char *)&land)){
106 if (land.lnd_own == player->cnum)
107 tot_mil += total_mil(&land);
109 if ((getvar(V_MILIT, (s_char *)§, EF_SECTOR)+tot_mil) * 10
110 < getvar(V_CIVIL, (s_char *)§, EF_SECTOR)) {
111 pr("Military control required to move goods.\n");
115 stype = sect.sct_type;
117 infected = getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_INFECT;
118 amt_src = getvar(vtype, (s_char *)§, EF_SECTOR);
119 if (!istest && amt_src <= 0) {
120 pr("No %s in %s\n", ip->i_name,
121 xyas(sect.sct_x, sect.sct_y, player->cnum));
125 mob = (int)sect.sct_mobil;
126 if (!istest && vtype == V_CIVIL && sect.sct_oldown != own) {
127 pr("You can't move conquered populace!\n");
131 pr("No mobility in %s\n",
132 xyas(sect.sct_x, sect.sct_y, player->cnum));
135 if (vtype == V_CIVIL) {
136 work = sect.sct_work;
138 pr("Warning: civil unrest\n");
139 loyal = sect.sct_loyal;
140 } else if (vtype == V_MILIT) {
145 sprintf(prompt, "Number of %s to test move? ", ip->i_name);
147 sprintf(prompt, "Number of %s to move? (max %d) ",
150 if ((amount = onearg(player->argp[3], prompt)) < 0)
152 if (!check_sect_ok(§))
154 if (amount > amt_src) {
156 pr("Note: there are actually only %d %s in %s,\nbut the test will be made for %d %s as you requested.\n",
158 xyas(sect.sct_x, sect.sct_y, player->cnum),
162 pr("Only moving %d.\n", amount);
166 if (!want_to_abandon(§, vtype, amount, 0)) {
167 pr("Move cancelled.\n");
171 if (!check_sect_ok(§))
176 packing = ip->i_pkg[dp->d_pkg];
177 if (packing > 1 && sect.sct_effic < 60)
179 weight = (double)amount * ip->i_lbs / packing;
181 * First remove commodities from source sector
184 getsect(x, y, &start);
185 if (start.sct_own != player->cnum) {
186 pr("Somebody has captured that sector!\n");
189 amt_src = getvar(vtype, (s_char *)&start, EF_SECTOR);
190 if (amt_src < amount) {
191 pr("Only %d %s left in %s!\n", amt_src,
192 ip->i_name,xyas(start.sct_x,start.sct_y,player->cnum));
198 putvar(vtype, amt_src, (s_char *)&start, EF_SECTOR);
199 start.sct_flags |= MOVE_IN_PROGRESS;
204 * Now parse the path and return ending sector.
206 dam = (istest ? 0 : 1);
207 if (dam && !chance(weight / 200.0))
209 mcost = move_ground((s_char *)ip, §, &endsect,
210 (double)sect.sct_mobil, weight, player->argp[4], cmd_move_map, 0, &dam);
213 left = commdamage(amount, dam, ip->i_vtype);
216 pr("%d of the %s you were moving were destroyed!\nOnly %d %s made it to %s\n",
221 xyas(endsect.sct_x, endsect.sct_y, player->cnum));
223 pr("All of the %s you were moving were destroyed!\n",ip->i_name);
230 pr("Total movement cost = %d\n",mcost);
232 pr("No mobility used\n");
236 pr("Move aborted\n");
238 sect.sct_mobil = (u_char)mob;
240 } else if (!istest) {
242 * decrement mobility appropriately.
244 getsect(x, y, &start);
245 mob = start.sct_mobil;
251 start.sct_mobil = (u_char)mob;
252 left = start.sct_mobil;
254 getsect(endsect.sct_x, endsect.sct_y, §);
258 * Check for lotsa stuff
260 if (sect.sct_own != player->cnum) {
261 if (sect.sct_own != 0)
262 pr("Somebody has captured that sector!\n");
265 if (vtype == V_CIVIL && getvar(V_CIVIL, (s_char *)§, EF_SECTOR) &&
266 sect.sct_oldown != player->cnum) {
267 pr("Your civilians don't want to stay!\n");
271 amt_dst = getvar(vtype, (s_char *)§, EF_SECTOR);
272 if (32767 - amt_dst < amount) {
273 pr("Only enough room for %d in %s. The goods will be returned.\n",
274 32767 - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum));
279 pr("%d mob left in %s\n", left,
280 xyas(start.sct_x,start.sct_y,player->cnum));
282 /* If the sector that things are going to is no longer
283 owned by the player, and was the starting sector,
284 try to find somewhere to dump the stuff. If nowhere
285 to dump it, it disappears. */
286 if (sect.sct_own != player->cnum &&
287 sect.sct_x == x && sect.sct_y == y) {
288 pr("Can't return the goods, since the starting point is no longer\n");
289 pr("owned by you.\n");
290 /* First lets see if there is one with room */
291 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
292 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
293 if (tsct.sct_own != player->cnum)
295 amt_dst = getvar(vtype, (s_char *)&tsct, EF_SECTOR);
296 if (32767 - amt_dst < amount)
302 /* Find any sector if none with room */
303 for (n = DIR_FIRST; n <= DIR_LAST; n++) {
304 getsect(x + diroff[n][0], y + diroff[n][1], &tsct);
305 if (tsct.sct_own != player->cnum)
311 pr("The goods had nowhere to go, and were destroyed.\n");
312 sect.sct_flags &= ~MOVE_IN_PROGRESS;
317 pr("The goods were dumped into %s.\n",
318 xyas(tsct.sct_x, tsct.sct_y, player->cnum));
319 getsect(tsct.sct_x, tsct.sct_y, §);
322 amt_dst = getvar(vtype, (s_char *)§, EF_SECTOR);
323 if (32767 - amt_dst < amount) {
324 amount = 32767 - amt_dst;
325 pr("Only room for %d, the rest were lost.\n", amount);
329 if (putvar(vtype, amount + amt_dst, (s_char *)§, EF_SECTOR) < 0) {
330 pr("No more room in %s. The goods were lost.\n",
331 xyas(sect.sct_x, sect.sct_y, player->cnum));
332 /* charge the player mobility anyway */
336 * Now add commodities to destination sector,
337 * along with plague that came along for the ride.
338 * Takeover unowned sectors if not deity.
340 if (infected && getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == 0)
341 putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)§, EF_SECTOR);
342 if (vtype == V_CIVIL) {
344 sect.sct_loyal =( (amt_dst * sect.sct_loyal) +
345 (amount * loyal) ) / (amt_dst+amount);
346 sect.sct_work =( (amt_dst * sect.sct_work) +
347 (amount * work) ) / (amt_dst+amount);
348 } else { /* ! NEW_WORK */
350 /* It only takes one bad apple... */
351 if (sect.sct_loyal < loyal)
352 sect.sct_loyal = loyal;
353 if (sect.sct_work > work)
354 sect.sct_work = work;
358 getsect(x, y, &start);
359 start.sct_flags &= ~MOVE_IN_PROGRESS;
365 * Pretty tacky, but it works.
366 * If more commands start doing this, then
367 * rewrite map to do the right thing.
369 /* I think this is no longer used, check subs/move.c:move_ground() */
372 cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg)
374 player->argp[1] = arg;
375 player->argp[2] = "";
376 player->argp[3] = "";
377 player->argp[4] = "";
378 player->argp[5] = "";
384 want_to_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
388 /* First, would we be abandoning it? If not, just return that it's
390 if (!would_abandon(sp, vtype, amnt, lp))
393 sprintf(prompt, "Do you really want to abandon %s [yn]? ",
394 xyas(sp->sct_x, sp->sct_y, player->cnum));
396 /* now, if they say yes that it's ok, just return 1 */
405 would_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp)
408 int mil, civs, loyalcivs;
410 if ((vtype != V_CIVIL) && (vtype != V_MILIT))
413 bcopy((s_char *)sp,(s_char *)§,sizeof(struct sctstr));
415 mil = getvar(V_MILIT, (s_char *)sp, EF_SECTOR);
416 civs = getvar(V_CIVIL, (s_char *)sp, EF_SECTOR);
418 if (vtype == V_MILIT)
421 if (vtype == V_CIVIL)
424 if (sp->sct_own == sp->sct_oldown)
429 /* If they have a military unit there, they still own it */
430 if (sp->sct_own != 0 && ((loyalcivs == 0) && (mil == 0) &&
431 (has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp) == 0)))