]> git.pond.sub.org Git - empserver/blob - src/lib/update/nav_ship.c
COPYING duplicates information from README. Remove. Move GPL from
[empserver] / src / lib / update / nav_ship.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2006, 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 files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  nav_ship.c: Navigate ships and such
29  * 
30  *  Known contributors to this file:
31  *     Chad Zabel, 1994
32  *     Ken Stevens, 1995
33  */
34
35 #include <config.h>
36
37 #include "misc.h"
38
39 #include <ctype.h>
40 #include "ship.h"
41 #include "sect.h"
42 #include "xy.h"
43 #include "nsc.h"
44 #include "nat.h"
45 #include "path.h"
46 #include "file.h"
47 #include "item.h"
48 #include "optlist.h"
49 #include "player.h"
50 #include "update.h"
51 #include "subs.h"
52 #include "common.h"
53 #include <stdlib.h>
54
55 static void swap(struct shpstr *);
56
57 static void
58 scuttle_it(struct shpstr *sp)
59 {
60     struct sctstr *sectp;
61
62     sp->shp_autonav &= ~AN_SCUTTLE;
63     if (!(sectp = getsectp(sp->shp_x, sp->shp_y))) {
64         wu(0, 0, "bad sector (%d,%d) ship %d\n", sp->shp_x, sp->shp_y,
65            sp->shp_uid);
66         return;
67     }
68     if (sectp->sct_type != SCT_HARBR || sectp->sct_effic < 2) {
69         wu(0, sp->shp_own,
70            "%s is not in a harbor at least 2%% eff!  Not scuttling.\n",
71            prship(sp));
72         return;
73     }
74     if (opt_TRADESHIPS) {
75         if (!(mchr[(int)sp->shp_type].m_flags & M_TRADE)) {
76             wu(0, sp->shp_own, "You can only autoscuttle trade ships!\n");
77             return;
78         }
79     }
80     wu(0, sp->shp_own, "Scuttling %s in sector %s\n",
81        prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own));
82     if (opt_TRADESHIPS) {
83         scuttle_tradeship(sp, 0);
84     }
85     scuttle_ship(sp);
86 }
87
88 static void
89 nav_check_atdest(struct shpstr *sp)
90 {
91     if ((sp->shp_x == sp->shp_destx[0]) && (sp->shp_y == sp->shp_desty[0])) {
92         if ((sp->shp_destx[0] == sp->shp_destx[1]) &&
93             (sp->shp_desty[0] == sp->shp_desty[1])) {
94
95             /* End of road */
96
97             sp->shp_autonav &= ~AN_AUTONAV;
98             wu(0, sp->shp_own, "%s arrived at %s, finished\n",
99                prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own));
100             if (sp->shp_autonav & AN_SCUTTLE) {
101                 scuttle_it(sp);
102             }
103         } else {
104             /* unload all cargo */
105             unload_it(sp);
106             wu(0, sp->shp_own, "%s arrived at %s\n",
107                prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own));
108             /* Swap */
109             swap(sp);
110         }
111     } else
112         sp->shp_autonav &= ~AN_LOADING;
113 }
114
115 /* flip the 2 fields that deal with autonav movement. */
116 /* CZ 6/1/94                                          */
117
118 static void
119 swap(struct shpstr *sp)
120 {
121     coord tcord;
122     i_type tcomm[TMAX];
123     short lev[TMAX];
124     int i;
125
126     tcord = sp->shp_destx[0];
127     sp->shp_destx[0] = sp->shp_destx[1];
128     sp->shp_destx[1] = tcord;
129     tcord = sp->shp_desty[0];
130     sp->shp_desty[0] = sp->shp_desty[1];
131     sp->shp_desty[1] = tcord;
132
133     for (i = 0; i < TMAX; ++i) {
134         lev[i] = sp->shp_lstart[i];
135         tcomm[i] = sp->shp_tstart[i];
136     }
137
138     for (i = 0; i < TMAX; ++i) {
139         sp->shp_lstart[i] = sp->shp_lend[i];
140         sp->shp_tstart[i] = sp->shp_tend[i];
141     }
142
143     for (i = 0; i < TMAX; ++i) {
144         sp->shp_lend[i] = lev[i];
145         sp->shp_tend[i] = tcomm[i];
146     }
147
148     /* set load bit */
149     sp->shp_autonav |= AN_LOADING;
150 }
151
152 /*  New Autonav code.
153  *  Chad Zabel
154  *  6-1-94
155  */
156
157 static int
158 nav_loadship(struct shpstr *sp, natid cnum)
159 {
160     struct sctstr *sectp;
161     int i, landown, shipown, didsomething[TMAX], rel;
162
163     for (i = 0; i < TMAX; i++)
164         didsomething[i] = 0;
165
166     /* Turn off the loading flag.
167      * if any of the loads fail on the ship
168      * it will be turned back on.
169      */
170
171     sp->shp_autonav &= ~AN_LOADING;
172
173     if (!(sectp = getsectp(sp->shp_x, sp->shp_y)))
174         return RET_SYS;         /* safety */
175     /* I suspect RET_SYS isn't really what you want here --dfp */
176
177
178     landown = sectp->sct_own;
179     shipown = sp->shp_own;
180     rel = getrel(getnatp(sectp->sct_own), cnum);
181
182     /* loop through each field for that ship */
183     for (i = 0; i < TMAX; ++i) {
184         /* check and see if the data fields have been set. */
185
186         if (sp->shp_tend[i] == I_NONE || sp->shp_lend[i] == 0) {
187             /* nothing to do move on. */
188             didsomething[i] = 1;
189             continue;
190         }
191         if (landown == 0) {
192             /* either sea or deity harbor */
193             didsomething[i] = 1;
194             continue;
195         }
196         if (!sect_has_dock(sectp)) {
197             /* we can only load in harbors */
198             didsomething[i] = 1;
199             continue;
200         }
201         if (landown == shipown || rel >= FRIENDLY)
202             didsomething[i] = load_it(sp, sectp, i);
203     }
204
205     /* check for any unsucessful loads */
206     /* if we have any return 0 to stop */
207     /* the nav_ship loop.              */
208
209     for (i = 0; i < TMAX; i++) {
210         if (didsomething[i] == 0)
211             return 0;
212     }
213     /* All loads were succesful */
214     return 1;
215 }
216
217 /* new autonav code.
218  * 
219  * 1. Try and move to the next sector/harbor given by the player.
220  * 2. Once we reach a harbor try and load all cargo holds for that ship.
221  * 3. If the ship reaches its max levels set by the player try to use
222  *    up all mobility getting to the next harbor.
223  * Continue to loop until the ship runs out of mobility, a load fails,
224  * the ship gets sunk (forts,ect..), the ship hits a mine.
225  *
226  * A check has been added for fuel so ships don't end up running
227  * out of mobility in the ocean.
228  *
229  * Questions, bugs (fixes) , or new ideas should be directed at
230  * Chad Zabel.  
231  * 6-1-94   
232  * Modified to use shp_nav by Ken Stevens 1995
233  */
234 int
235 nav_ship(struct shpstr *sp)
236 {
237     struct sctstr *sectp;
238     char *cp;
239     int stopping;
240     int quit;
241     int didsomething = 0;
242     int max_amt, food_amt;
243     char buf[1024];
244     struct emp_qelem ship_list;
245     struct emp_qelem *qp, *newqp;
246     struct mlist *mlp;
247     int dummyint;
248     double dummydouble;
249     int dir;
250     natid cnum;
251     struct mchrstr *mcp, *vship;
252
253     /* just return if no autonaving to do for this ship */
254     if (!(sp->shp_autonav & AN_AUTONAV) || (sp->shp_autonav & AN_STANDBY))
255         return RET_OK;
256
257     cnum = sp->shp_own;
258     vship = mcp = &mchr[(int)sp->shp_type];
259
260     /* Make a list of one ships so we can use the navi.c code */
261     emp_initque(&ship_list);
262     mlp = malloc(sizeof(struct mlist));
263     mlp->mcp = mchr + sp->shp_type;
264     mlp->ship = *sp;
265     mlp->mobil = (double)sp->shp_mobil;
266     emp_insque(&mlp->queue, &ship_list);
267
268     quit = 1;                   /* setup loop, we want to check it 1 time. */
269
270     do {
271         if ((sp->shp_mobil > 0) && (!(sp->shp_autonav & AN_LOADING)) &&
272             (!(sp->shp_autonav & AN_STANDBY))) {
273             shp_nav(&ship_list, &dummydouble, &dummydouble, &dummyint,
274                     sp->shp_own);
275             if (QEMPTY(&ship_list))
276                 return RET_OK;
277             /* before we move check to see if ship needs fuel. */
278             sectp = getsectp(sp->shp_x, sp->shp_y);
279             if (opt_FUEL &&
280                 sectp->sct_own != 0 &&
281                 sp->shp_fuel <= 0 && mlp->mcp->m_fuelu != 0)
282                 auto_fuel_ship(sp);
283             mlp->ship.shp_fuel = sp->shp_fuel;
284
285             cp = BestShipPath(buf, sp->shp_x, sp->shp_y,
286                               sp->shp_destx[0], sp->shp_desty[0],
287                               sp->shp_own);
288             if (cp == 0 || (*cp == '\0') || (*cp == '?')) {
289                 wu(0, cnum,
290                    "%s bad path, ship put on standby\n", prship(sp));
291                 sp->shp_autonav |= AN_STANDBY;
292                 putship(sp->shp_uid, sp);
293
294                 /* We need to free the ship list */
295                 qp = ship_list.q_forw;
296                 while (qp != &ship_list) {
297                     newqp = qp->q_forw;
298                     emp_remque(qp);
299                     free(qp);
300                     qp = newqp;
301                 }
302                 return RET_SYN;
303             }
304             stopping = 0;
305
306             while (*cp && !stopping && sp->shp_own && mlp->mobil > 0.0) {
307                 dir = diridx(*cp++);
308                 stopping |= shp_nav_one_sector(&ship_list, dir,
309                                                sp->shp_own, 0);
310             }
311
312             /* Ship not sunk */
313             if (sp->shp_own)
314                 nav_check_atdest(sp);
315         }
316
317         quit = 0;               /* stop loop */
318
319         /* Try to load the ship */
320         if (sp->shp_autonav & AN_LOADING) {
321             didsomething = nav_loadship(sp, cnum);
322             if (didsomething)
323                 quit = 1;
324         }
325         /* special case for fishing boats */
326         if ((mchr[(int)sp->shp_type].m_flags & M_FOOD) == 1) {
327             food_amt = sp->shp_item[I_FOOD];
328             max_amt = vship->m_item[I_FOOD];
329             sectp = getsectp(sp->shp_x, sp->shp_y);
330
331             if (food_amt < max_amt && (sectp->sct_own == 0))
332                 quit = 0;
333         }
334         /* reset flag and check if we can move. */
335
336     } while (quit);             /* end loop */
337
338     putship(sp->shp_uid, sp);
339
340     /* We need to free the ship list (just in case) */
341     qp = ship_list.q_forw;
342     while (qp != &ship_list) {
343         newqp = qp->q_forw;
344         emp_remque(qp);
345         free(qp);
346         qp = newqp;
347     }
348     return RET_OK;
349 }