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