2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2013, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure, Markus Armbruster
6 * Empire 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 3 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, see <http://www.gnu.org/licenses/>.
21 * See files README, COPYING and CREDITS in the root of the source
22 * tree for related information and legal notices. It is expected
23 * that future projects/authors will amend these files as needed.
27 * move.c: Move something somewhere.
29 * Known contributors to this file:
30 * Markus Armbruster, 2004-2011
43 #include "prototypes.h"
46 static int move_map(coord curx, coord cury, char *arg);
49 move_ground(struct sctstr *start, struct sctstr *end,
50 double weight, char *path,
51 int (*map)(coord, coord, char *, char *),
52 int exploring, int *dam)
56 coord curx, cury, oldx, oldy;
64 double mobility = start->sct_mobil;
78 if (path && sarg_xy(path, &dx, &dy)) {
79 if (dx == start->sct_x && dy == start->sct_y) {
80 pr("Start sector is ending sector!\n");
83 pr("Looking for best path to %s\n", path);
84 total_mcost = path_find(start->sct_x, start->sct_y, dx, dy,
85 player->cnum, MOB_MOVE);
88 pr("No owned path exists!\n");
90 len = path_find_route(buf, sizeof(buf),
91 start->sct_x, start->sct_y, dx, dy);
93 if (len < sizeof(buf))
94 strcpy(buf + len, "h");
97 if (len >= sizeof(buf))
98 pr("Can't handle path to %s, it's too long, sorry.\n",
99 xyas(dx, dy, player->cnum));
102 pr("Using best path '%s', movement cost %1.3f\n",
104 if (total_mcost * weight > mobility) {
105 pr("Not enough mobility to go all the way."
106 " Nothing moved.\n");
116 if (getsect(curx, cury, §) < 0) {
117 logerror("move_path: getsect %d,%d", curx, cury);
123 if (!movstr || *movstr == 0) {
125 map(curx, cury, NULL, NULL);
127 move_map(curx, cury, NULL);
129 sprintf(prompt, "<%.1f: %c %s> ", mobility,
130 dchr[sect.sct_type].d_mnem,
131 xyas(sect.sct_x, sect.sct_y, player->cnum));
132 movstr = getstring(prompt, buf);
134 if (movstr && sarg_xy(movstr, &dx, &dy)) {
135 mv_cost = path_find(sect.sct_x, sect.sct_y, dx, dy,
136 player->cnum, MOB_MOVE);
138 pr("Can't get to %s from here!\n",
139 xyas(dx, dy, player->cnum));
142 len = path_find_route(buf, sizeof(buf),
143 sect.sct_x, sect.sct_y, dx, dy);
144 if (len < sizeof(buf))
145 strcpy(buf + len, "h");
147 if (len >= sizeof(buf)) {
148 pr("Can't handle path to %s, it's too long, sorry.\n",
149 xyas(dx, dy, player->cnum));
152 if ((mv_cost * weight) > mobility) {
153 pr("Not enough mobility to go all the way. Nothing moved.\n");
157 pr("Using best path '%s', movement cost %1.3f\n",
163 if (!movstr || *movstr == 0) {
164 buf[0] = dirch[DIR_STOP];
168 if ((dir = chkdir(*movstr, DIR_STOP, DIR_MAP)) < 0) {
169 pr("\"%c\" is not legal...", *movstr);
170 direrr("'%c' to stop ", "'%c' to view ", "& '%c' to map\n");
174 if (dir == DIR_MAP) {
175 parse(movstr, scanspace, argp, NULL, NULL, NULL);
177 pr("Use of '%c' without a space before its argument is deprecated.\n"
178 "Support for it will go away in a future release\n",
181 argp[1] = argp[0] + 1;
184 map(curx, cury, argp[1], argp[2]);
191 if (dir == DIR_VIEW) {
192 pr("%d%% %s with %d civilians.\n", sect.sct_effic,
193 dchr[sect.sct_type].d_name, sect.sct_item[I_CIVIL]);
197 * now see if we can move into the
198 * next sector. Mobility, terrain,
199 * or ownership may prevent us.
201 tmpx = curx + diroff[dir][0];
202 tmpy = cury + diroff[dir][1];
203 if (getsect(tmpx, tmpy, &next) < 0) {
204 pr("You can't go there...\n");
209 if ((next.sct_type == SCT_SANCT) &&
210 (next.sct_own != player->cnum)) {
211 pr("Converts, huh?\n");
215 sect_mcost = sector_mcost(&next, MOB_MOVE);
216 if ((!player->owner && (!exploring
217 || next.sct_item[I_MILIT]
218 || next.sct_item[I_CIVIL]))
219 || sect_mcost == -1.0) {
220 /* already-owned, or prohibited terrain */
221 pr("You can't go there...\n");
225 sect_mcost *= weight;
226 if (sect_mcost > mobility) {
227 pr("Not enough mobility. ");
228 pr("You can't go there...\n");
232 mobility -= sect_mcost;
233 total_mcost += sect_mcost;
237 if (cury != start->sct_y)
239 if (curx != start->sct_x)
245 *dam += check_lmines(sect.sct_x, sect.sct_y, weight);
249 * Check and see if anyone will interdict us
251 if (takedam && chance(weight / 100.0) &&
252 ((curx != oldx) || (cury != oldy)))
253 *dam += ground_interdict(curx, cury, player->cnum,
259 intcost = (int)total_mcost;
262 if ((start->sct_x == end->sct_x) && (start->sct_y == end->sct_y)
266 if (chance(total_mcost - intcost))
274 move_map(coord curx, coord cury, char *arg)
282 snxtsct_dist(&ns, curx, cury, 1);
284 while (i < 7 && nxtsct(&ns, §)) {
285 /* Nasty: this relies on the iteration order */
286 view[i] = dchr[sect.sct_type].d_mnem;
287 switch (sect.sct_type) {
295 if (sect.sct_own != player->cnum && !player->god)
299 changed += map_set(player->cnum, ns.x, ns.y, view[i], 0);
303 writemap(player->cnum);
304 if (!getsect(curx, cury, §))
306 pr(" %c %c eff mob civ mil uw food work avail\n",
308 pr(" %c %c %c %3d %3d %4d %4d %4d %4d %3d %3d\n",
309 view[2], view[3], view[4],
310 sect.sct_effic, sect.sct_mobil,
311 sect.sct_item[I_CIVIL], sect.sct_item[I_MILIT], sect.sct_item[I_UW],
312 sect.sct_item[I_FOOD], sect.sct_work, sect.sct_avail);
313 pr(" %c %c\n", view[5], view[6]);
318 fly_map(coord curx, coord cury)
325 snxtsct_dist(&ns, curx, cury, 1);
327 while (i < 7 && nxtsct(&ns, §)) {
328 /* Nasty: this relies on the iteration order */
329 if (!(view[i] = player->bmap[sect.sct_uid]))
334 pr(" %c %c\n", view[0], view[1]);
335 pr(" %c %c %c\n", view[2], view[3], view[4]);
336 pr(" %c %c\n", view[5], view[6]);
341 check_lmines(coord x, coord y, double weight)
346 getsect(x, y, §);
347 if (SCT_LANDMINES(§) > 0 &&
348 sect.sct_oldown != player->cnum &&
349 chance(DMINE_LHITCHANCE(sect.sct_mines)) && chance(weight / 100.0)) {
351 pr("Blammo! Landmines detected! in %s ",
352 xyas(sect.sct_x, sect.sct_y, player->cnum));
356 pr("%d damage sustained.\n", dam);