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