]> git.pond.sub.org Git - empserver/blob - src/lib/update/nav_ship.c
Sectors need space for items, deliveries and distribution thresholds.
[empserver] / src / lib / update / nav_ship.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, 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  *  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 "misc.h"
36
37 #include <ctype.h>
38 #include "var.h"
39 #include "ship.h"
40 #include "sect.h"
41 #include "news.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(register struct shpstr *);
56
57 static void
58 scuttle_it(register 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(register 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(register struct shpstr *sp)
120 {
121     coord tcord;
122     s_char 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(register struct shpstr *sp, natid cnum)
159 {
160     struct sctstr *sectp;
161     s_char item;
162     int i, landown, shipown, level, didsomething[TMAX], rel;
163
164     for (i = 0; i < TMAX; i++)
165         didsomething[i] = 0;
166
167     /* Turn off the loading flag.
168      * if any of the loads fail on the ship
169      * it will be turned back on.
170      */
171
172     sp->shp_autonav &= ~AN_LOADING;
173
174     if (!(sectp = getsectp(sp->shp_x, sp->shp_y)))
175         return RET_SYS;         /* safety */
176     /* I suspect RET_SYS isn't really what you want here --dfp */
177
178
179     landown = sectp->sct_own;
180     shipown = sp->shp_own;
181     rel = getrel(getnatp(sectp->sct_own), cnum);
182
183     /* loop through each field for that ship */
184     for (i = 0; i < TMAX; ++i) {
185         item = sp->shp_tend[i]; /* commodity */
186         level = sp->shp_lend[i];        /* amount    */
187
188         /* check and see if the data fields have been set. */
189
190         if (item == ' ' || level == 0) {
191             /* nothing to do move on. */
192             didsomething[i] = 1;
193             continue;
194         }
195         if (landown == 0) {
196             /* either sea or deity harbor */
197             didsomething[i] = 1;
198             continue;
199         }
200         if (sectp->sct_type != SCT_HARBR &&
201             (!opt_BIG_CITY || sectp->sct_type != SCT_CAPIT)) {
202             /* we can only load in harbors */
203             didsomething[i] = 1;
204             continue;
205         }
206         if (landown == shipown || rel >= FRIENDLY)
207             didsomething[i] = load_it(sp, sectp, i);
208     }
209
210     /* check for any unsucessful loads */
211     /* if we have any return 0 to stop */
212     /* the nav_ship loop.              */
213
214     for (i = 0; i < TMAX; i++) {
215         if (didsomething[i] == 0)
216             return 0;
217     }
218     /* All loads were succesful */
219     return 1;
220 }
221
222 /* new autonav code.
223  * 
224  * 1. Try and move to the next sector/harbor given by the player.
225  * 2. Once we reach a harbor try and load all cargo holds for that ship.
226  * 3. If the ship reaches its max levels set by the player try to use
227  *    up all mobility getting to the next harbor.
228  * Continue to loop until the ship runs out of mobility, a load fails,
229  * the ship gets sunk (forts,ect..), the ship hits a mine.
230  *
231  * A check has been added for fuel so ships don't end up running
232  * out of mobility in the ocean.
233  *
234  * Questions, bugs (fixes) , or new ideas should be directed at
235  * Chad Zabel.  
236  * 6-1-94   
237  * Modified to use shp_nav by Ken Stevens 1995
238  */
239 int
240 nav_ship(register struct shpstr *sp)
241 {
242     struct sctstr *sectp;
243     s_char *cp;
244     int stopping;
245     int quit;
246     int didsomething = 0;
247     int max_amt, food_amt;
248     s_char buf[1024];
249     struct emp_qelem ship_list;
250     struct emp_qelem *qp, *newqp;
251     struct mlist *mlp;
252     int dummyint;
253     double dummydouble;
254     int dir;
255     natid cnum;
256     struct mchrstr *mcp, *vship;
257
258     /* just return if no autonaving to do for this ship */
259     if (!(sp->shp_autonav & AN_AUTONAV) || (sp->shp_autonav & AN_STANDBY))
260         return RET_OK;
261
262     cnum = sp->shp_own;
263     vship = mcp = &mchr[(int)sp->shp_type];
264
265     /* Make a list of one ships so we can use the navi.c code */
266     emp_initque(&ship_list);
267     mlp = (struct mlist *)malloc(sizeof(struct mlist));
268     mlp->mcp = mchr + sp->shp_type;
269     mlp->ship = *sp;
270     mlp->mobil = (double)sp->shp_mobil;
271     emp_insque(&mlp->queue, &ship_list);
272
273     quit = 1;                   /* setup loop, we want to check it 1 time. */
274
275     do {
276         if ((sp->shp_mobil > 0) && (!(sp->shp_autonav & AN_LOADING)) &&
277             (!(sp->shp_autonav & AN_STANDBY))) {
278             shp_nav(&ship_list, &dummydouble, &dummydouble, &dummyint,
279                     sp->shp_own);
280             if (QEMPTY(&ship_list))
281                 return RET_OK;
282             /* before we move check to see if ship needs fuel. */
283             sectp = getsectp(sp->shp_x, sp->shp_y);
284             if (opt_FUEL &&
285                 sectp->sct_own != 0 &&
286                 sp->shp_fuel <= 0 && mlp->mcp->m_fuelu != 0)
287                 auto_fuel_ship(sp);
288             mlp->ship.shp_fuel = sp->shp_fuel;
289
290             cp = BestShipPath(buf, sp->shp_x, sp->shp_y,
291                               sp->shp_destx[0], sp->shp_desty[0],
292                               sp->shp_own);
293             if (cp == 0 || (*cp == '\0') || (*cp == '?')) {
294                 wu(0, cnum,
295                    "%s bad path, ship put on standby\n", prship(sp));
296                 sp->shp_autonav |= AN_STANDBY;
297                 putship(sp->shp_uid, (s_char *)sp);
298
299                 /* We need to free the ship list */
300                 qp = ship_list.q_forw;
301                 while (qp != &(ship_list)) {
302                     newqp = qp->q_forw;
303                     emp_remque(qp);
304                     free((s_char *)qp);
305                     qp = newqp;
306                 }
307                 return RET_SYN;
308             }
309             stopping = 0;
310
311             while (*cp && !stopping && sp->shp_own && mlp->mobil > 0.0) {
312                 dir = chkdir(*cp++, DIR_STOP, DIR_LAST);
313
314                 stopping |= shp_nav_one_sector(&ship_list, dir,
315                                                sp->shp_own, 0);
316             }
317
318 /*                      sp->shp_mobil = (int) mobil;
319  */
320             /* Ship not sunk */
321             if (sp->shp_own)
322                 nav_check_atdest(sp);
323         }
324
325         quit = 0;               /* stop loop */
326
327         /* Try to load the ship */
328         if (sp->shp_autonav & AN_LOADING) {
329             didsomething = nav_loadship(sp, cnum);
330             if (didsomething)
331                 quit = 1;
332         }
333         /* special case for fishing boats */
334         if ((mchr[(int)sp->shp_type].m_flags & M_FOOD) == 1) {
335             food_amt = sp->shp_item[I_FOOD];
336             max_amt = vl_find(V_FOOD, vship->m_vtype,
337                               vship->m_vamt, vship->m_nv);
338             sectp = getsectp(sp->shp_x, sp->shp_y);
339
340             if (food_amt < max_amt && (sectp->sct_own == 0))
341                 quit = 0;
342         }
343         /* reset flag and check if we can move. */
344
345     } while (quit);             /* end loop */
346
347     putship(sp->shp_uid, sp);
348
349     /* We need to free the ship list (just in case) */
350     qp = ship_list.q_forw;
351     while (qp != &(ship_list)) {
352         newqp = qp->q_forw;
353         emp_remque(qp);
354         free((s_char *)qp);
355         qp = newqp;
356     }
357     return RET_OK;
358 }