2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2004, 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 something somewhere.
30 * Known contributors to this file:
46 #include "prototypes.h"
48 static int move_map(s_char *what, coord curx, coord cury, s_char *arg);
51 move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
52 double weight, s_char *path,
53 int (*map)(s_char *, coord, coord, s_char *), int exploring,
56 struct sctstr sect, ending_sect;
57 struct sctstr next, dsect;
58 coord curx, cury, oldx, oldy;
65 double mobility = (double)start->sct_mobil;
68 int takedam = (*dam), out = 0;
78 if (path && sarg_xy(path, &dx, &dy) && getsect(dx, dy, &ending_sect)) {
79 if ((ending_sect.sct_x == start->sct_x) &&
80 (ending_sect.sct_y == start->sct_y)) {
81 pr("Start sector is ending sector!\n");
84 pr("Looking for best path to %s\n", path);
85 path = BestLandPath(buf2, start, &ending_sect, &total_mcost,
87 if (exploring && (path != (s_char *)0)) /* take off the 'h' */
88 *(path + strlen(path) - 1) = '\0';
89 if (path == (s_char *)0)
90 pr("No owned path exists!\n");
92 pr("Using best path '%s', movement cost %1.3f\n",
94 strncpy(bpath, path, sizeof(bpath));
97 if ((total_mcost * weight) > mobility) {
98 pr("Not enough mobility to go all the way. Nothing moved.\n");
106 if (getsect(curx, cury, §) < 0) {
107 logerror("move_path: getsect %d,%d", curx, cury);
113 if (movstr == 0 || *movstr == 0) {
115 map(what, curx, cury, (s_char *)0);
117 move_map(what, curx, cury, (s_char *)0);
119 sprintf(prompt, "<%.1f: %c %s> ", mobility,
120 dchr[sect.sct_type].d_mnem,
121 xyas(sect.sct_x, sect.sct_y, player->cnum));
122 movstr = getstring(prompt, buf);
124 if (movstr && sarg_xy(movstr, &dx, &dy)) {
125 if (getsect(dx, dy, &dsect)) {
126 movstr = BestLandPath(buf2, §, &dsect, &mv_cost,
129 pr("Invalid destination sector!\n");
130 movstr = (s_char *)0;
133 if (movstr == (s_char *)0) {
134 pr("Can't get to %s from here!\n",
135 xyas(dx, dy, player->cnum));
136 movstr = (s_char *)0;
138 if ((mv_cost * weight) > mobility) {
139 pr("Not enough mobility to go all the way. Nothing moved.\n");
140 movstr = (s_char *)0;
142 pr("Using best path '%s', movement cost %1.3f\n",
144 strncpy(bpath, movstr, sizeof(bpath));
149 if (movstr == 0 || *movstr == 0) {
150 buf2[0] = dirch[DIR_STOP];
154 if ((dir = chkdir(*movstr, DIR_STOP, DIR_MAP)) < 0) {
155 pr("\"%c\" is not legal...", *movstr);
156 direrr("'%c' to stop ", "'%c' to view ", "& '%c' to map\n");
161 if (dir == DIR_MAP) {
163 map(what, curx, cury, movstr + 1);
166 } else if (dir == DIR_STOP)
168 else if (dir == DIR_VIEW) {
169 pr("%d%% %s with %d civilians.\n", sect.sct_effic,
170 dchr[sect.sct_type].d_name,
171 sect.sct_item[I_CIVIL]);
175 * now see if we can move into the
176 * next sector. Mobility, terrain,
177 * or ownership may prevent us.
179 tmpx = curx + diroff[dir][0];
180 tmpy = cury + diroff[dir][1];
181 if (getsect(tmpx, tmpy, &next) < 0) {
182 pr("You can't go there...\n");
187 if ((next.sct_type == SCT_SANCT) &&
188 (next.sct_own != player->cnum)) {
189 pr("Converts, huh?\n");
193 sect_mcost = sector_mcost(&next, MOB_ROAD);
194 if ((!player->owner && (!exploring
195 || next.sct_item[I_MILIT]
196 || next.sct_item[I_CIVIL]))
197 || sect_mcost == -1.0) {
198 /* already-owned, or prohibited terrain */
199 pr("You can't go there...\n");
203 sect_mcost *= weight;
204 if (sect_mcost > mobility) {
205 pr("Not enough mobility. ");
206 pr("You can't go there...\n");
210 mobility -= sect_mcost;
211 total_mcost += sect_mcost;
215 if (cury != start->sct_y)
217 if (curx != start->sct_x)
223 *dam += check_lmines(sect.sct_x, sect.sct_y, weight);
227 * Check and see if anyone will interdict us
229 if (takedam && chance(weight / 100.0) &&
230 ((curx != oldx) || (cury != oldy)))
231 (*dam) += ground_interdict(curx, cury, player->cnum,
237 intcost = (int)total_mcost;
240 if ((start->sct_x == end->sct_x) && (start->sct_y == end->sct_y)
244 if (chance(total_mcost - intcost))
252 move_map(s_char *what, coord curx, coord cury, s_char *arg)
263 np = getnatp(player->cnum);
264 rel_x = xrel(np, curx);
265 rel_y = yrel(np, cury);
266 sprintf(range, "%d:%d,%d:%d", rel_x - 2, rel_x + 2, rel_y - 1,
269 /* This is necessary, otherwise move_map would attempt to pay */
270 /* attention to the conditional arguments left behind by such */
271 /* a command as "tran p -1,-1 ?eff=100".. It'd then only see */
272 /* 100% efficienct sects, and get all screwed up --ts */
273 if (!snxtsct(&ns, range))
276 while (i < 7 && nxtsct(&ns, §)) {
277 view[i] = dchr[sect.sct_type].d_mnem;
278 switch (sect.sct_type) {
286 if (sect.sct_own != player->cnum && !player->god)
290 changed += map_set(player->cnum, ns.x, ns.y, view[i], 0);
294 writemap(player->cnum);
295 if (!getsect(curx, cury, §))
297 pr(" %c %c eff mob civ mil uw food work avail\n",
299 pr(" %c %c %c %3d %3d %4d %4d %4d %4d %3d %3d\n",
300 view[2], view[3], view[4],
301 sect.sct_effic, sect.sct_mobil,
302 sect.sct_item[I_CIVIL], sect.sct_item[I_MILIT], sect.sct_item[I_UW],
303 sect.sct_item[I_FOOD], sect.sct_work, sect.sct_avail);
304 pr(" %c %c\n", view[5], view[6]);
309 fly_map(coord curx, coord cury)
319 np = getnatp(player->cnum);
320 rel_x = xrel(np, curx);
321 rel_y = yrel(np, cury);
322 sprintf(range, "%d:%d,%d:%d", rel_x - 2, rel_x + 2, rel_y - 1,
325 /* This is necessary, otherwise move_map would attempt to pay */
326 /* attention to the conditional arguments left behind by such */
327 /* a command as "tran p -1,-1 ?eff=100".. It'd then only see */
328 /* 100% efficienct sects, and get all screwed up --ts */
330 if (!snxtsct(&ns, range))
333 while (i < 7 && nxtsct(&ns, §)) {
334 if (!(view[i] = player->bmap[sctoff(ns.x, ns.y)]))
339 pr(" %c %c\n", view[0], view[1]);
340 pr(" %c %c %c\n", view[2], view[3], view[4]);
341 pr(" %c %c\n", view[5], view[6]);
346 check_lmines(coord x, coord y, double weight)
351 getsect(x, y, §);
352 if (sect.sct_mines > 0 &&
353 sect.sct_oldown != player->cnum &&
354 chance(DMINE_LHITCHANCE(sect.sct_mines)) && chance(weight / 100.0)) {
356 pr("Blammo! Landmines detected! in %s ",
357 xyas(sect.sct_x, sect.sct_y, player->cnum));
361 pr("%d damage sustained.\n", dam);