]> git.pond.sub.org Git - empserver/blob - src/lib/subs/paths.c
(mcost): Unused, remove.
[empserver] / src / lib / subs / paths.c
1 /*
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
5  *
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.
10  *
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.
15  *
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
19  *
20  *  ---
21  *
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.
25  *
26  *  ---
27  *
28  *  path.c: Routines associated with paths, directions, etc.
29  * 
30  *  Known contributors to this file:
31  *   
32  */
33
34 #include "misc.h"
35 #include "player.h"
36 #include "xy.h"
37 #include "path.h"
38 #include "nat.h"
39 #include "sect.h"
40 #include "file.h"
41 #include "prototypes.h"
42
43 int
44 getdir(s_char *prompt, s_char *stop_msg, s_char *view_msg,
45        s_char *bomb_msg)
46 {
47     register int max_dir;
48     register int min_dir;
49     register int dir_num;
50     s_char buf[1024];
51
52     if (stop_msg != 0)
53         min_dir = DIR_STOP;
54     else
55         min_dir = DIR_FIRST;
56     if (view_msg == 0)
57         max_dir = DIR_LAST;
58     else
59         max_dir = DIR_VIEW;
60     while (1) {
61         if (getstring(prompt, buf) == 0 || *buf == 0)
62             return -1;
63         dir_num = chkdir(buf[0], min_dir, max_dir);
64         if (dir_num >= min_dir)
65             break;
66         direrr(stop_msg, view_msg, bomb_msg);
67     }
68     return dir_num;
69 }
70
71 int
72 chkdir(s_char dir_char, int min_dir, int max_dir)
73 {
74     register int i;
75
76     for (i = min_dir; i <= max_dir; i++)
77         if (dir_char == dirch[i])
78             return i;
79     return -1;
80 }
81
82 void
83 direrr(s_char *stop_msg, s_char *view_msg, s_char *map_msg)
84 {
85     pr("Legal directions are:\n");
86     pr(" %c %c\n", dirch[DIR_UL], dirch[DIR_UR]);
87     pr("%c   %c\n", dirch[DIR_L], dirch[DIR_R]);
88     pr(" %c %c\n", dirch[DIR_DL], dirch[DIR_DR]);
89     if (stop_msg != 0)
90         pr(stop_msg, dirch[DIR_STOP]);
91     if (view_msg != 0)
92         pr(view_msg, dirch[DIR_VIEW]);
93     if (map_msg != 0)
94         pr(map_msg, dirch[DIR_MAP]);
95 }
96
97 /*
98  * return pointer to path; prompt user until a stop char
99  * or a bomb char have been entered.  A "bomb" char in
100  * this context is actually "execute" for the partial
101  * move commands, and isn't valid for those commands
102  * which do not accept partial moves.
103  */
104 s_char *
105 getpath(s_char *buf, s_char *arg, coord x, coord y, int onlyown,
106         int showdes, int showxy, int destinations)
107 {
108     s_char *p = buf;
109     s_char *bp;
110     s_char prompt[128];
111     coord dx, dy;
112     struct sctstr sect, dsect;
113     coord nx, ny;
114     int dir;
115     s_char *execute;
116     double mv_cost;
117
118     if (arg) {
119         strncpy(buf, arg, MAX_PATH_LEN - 1);
120         buf[MAX_PATH_LEN - 1] = 0;
121     } else {
122         *p = 0;
123     }
124
125     if (showxy)
126         execute = " & '%c' to execute\n";
127     else
128         execute = "\n";
129
130     getsect(x, y, &sect);
131     nx = x;
132     ny = y;
133
134   more:
135     while (*p) {
136         if (sarg_xy(p, &dx, &dy)) {
137             bp = 0;
138             if (destinations == P_NONE) {
139                 pr("Destination sectors not allowed here!\n");
140                 *p = 0;
141             }
142             if (getsect(dx, dy, &dsect)) {
143                 if (destinations == P_WALKING) {
144                     bp = BestLandPath(p, &sect, &dsect,
145                                       &mv_cost, MOB_ROAD);
146                 } else if (destinations == P_FLYING) {
147                     bp = BestAirPath(p, nx, ny, dx, dy);
148                 }
149             } else {
150                 pr("Invalid destination sector!\n");
151                 *p = 0;
152             }
153             if (bp) {
154                 pr("Using best path  '%s'\n", p);
155                 pr("Using total path '%s'\n", buf);
156                 return buf;
157             } else {
158                 pr("Can't get to %s from here!\n",
159                    xyas(nx, ny, player->cnum));
160                 *p = 0;
161             }
162             break;
163         }
164         dir = chkdir(*p, DIR_STOP, DIR_LAST);
165         if (dir < 0) {
166             pr("\"%c\" is not legal...", *p);
167             direrr("'%c' to stop", (s_char *)0, execute);
168             *p = 0;
169             break;
170         }
171         nx = x + diroff[dir][0];
172         ny = y + diroff[dir][1];
173         getsect(nx, ny, &sect);
174         if (onlyown && sect.sct_own != player->cnum) {
175             *p = 0;
176             pr("You don't own %s; you can't go there!\n",
177                xyas(nx, ny, player->cnum));
178             break;
179         }
180         if (dir == DIR_STOP || dir == DIR_MAP) {
181             p[1] = 0;
182             return buf;
183         }
184         if (++p - buf == MAX_PATH_LEN) {
185             pr("Path length may not exceed %d.\n", MAX_PATH_LEN);
186             pr("Aborting...\n");
187             *buf = 0;
188             return buf;
189         }
190         x = nx;
191         y = ny;
192     }
193     fly_map(x, y);
194     if (showdes) {
195         getsect(x, y, &sect);
196         sprintf(prompt, "<%c: %s> ", dchr[sect.sct_type].d_mnem,
197                 xyas(x, y, player->cnum));
198     } else {
199         sprintf(prompt, "<%d: %s> ", (int)(p - buf),
200                 xyas(x, y, player->cnum));
201     }
202     if (!(bp = getstring(prompt, p)) || !*bp) {
203         if (player->aborted)
204             *buf = 0;
205         return buf;
206     }
207     goto more;
208 }
209
210 /*
211  * fly move cost
212  */
213 /* ARGSUSED */
214 double
215 fcost(struct sctstr *sp, natid own)
216 {
217     return 1.0;
218 }
219
220 /*
221  * nav move cost
222  */
223 /* ARGSUSED */
224 double
225 ncost(struct sctstr *sp, natid own)
226 {
227     return 1.0;
228 }
229
230 /*
231  * return end x,y of path, and the base
232  * movement cost it takes to get there.
233  */
234 double
235 pathtoxy(s_char *path, coord *xp, coord *yp,
236          double (*cost) (struct sctstr *, natid))
237 {
238     struct sctstr s;
239     s_char *pp;
240     coord x;
241     coord y;
242     int val;
243     double m;
244     int c;
245
246     x = *xp;
247     y = *yp;
248     m = 0.0;
249     for (pp = path; *pp; pp++) {
250         if ((val = chkdir(*pp, DIR_STOP, DIR_LAST)) == 0)
251             break;
252         x += diroff[val][0];
253         y += diroff[val][1];
254         c = dirch[val];
255         if (c == DIR_STOP)
256             break;
257         if (!getsect(x, y, &s))
258             return -1.0;
259         m += cost(&s, s.sct_own);
260     }
261     *xp = xnorm(x);
262     *yp = ynorm(y);
263     return m;
264 }
265
266 /*
267  * return true if "who" owns the path starting at x,y
268  */
269 int
270 chkpath(natid who, s_char *path, coord x, coord y)
271 {
272     s_char *pp;
273     int val;
274     struct sctstr sect;
275
276     for (pp = path; *pp; pp++) {
277         if ((val = chkdir(*pp, DIR_STOP, DIR_LAST)) == 0)
278             break;
279         x += diroff[val][0];
280         y += diroff[val][1];
281         if (!getsect(x, y, &sect) || sect.sct_own != who)
282             return 0;
283     }
284     return 1;
285 }
286
287 void
288 pathrange(register coord cx, register coord cy, register s_char *pp,
289           int border, struct range *range)
290 {
291     int dir;
292
293     range->lx = cx;
294     range->hx = cx;
295     range->ly = cy;
296     range->hy = cy;
297     range->width = 0;
298     range->height = 0;
299     while ((dir = chkdir(*pp, DIR_FIRST, DIR_LAST)) >= 0) {
300         pp++;
301         cx += diroff[dir][0];
302         cy += diroff[dir][1];
303         if (cx < range->lx)
304             range->lx = cx;
305         if (cx > range->hx)
306             range->hx = cx;
307         if (cy < range->ly)
308             range->ly = cy;
309         if (cy > range->hy)
310             range->hy = cy;
311     }
312     range->lx = xnorm(range->lx - border * 2);
313     range->ly = ynorm(range->ly - border);
314     range->hx = xnorm(range->hx + border * 2 + 1);
315     range->hy = ynorm(range->hy + border + 1);
316     xysize_range(range);
317 }