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
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.
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.
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
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.
28 * sail.c: Sail ships during the update
30 * Known contributors to this file:
34 * Steve McClure, 1998-2000
54 cost_ship(struct shpstr *sp, struct fltelemstr *ep, struct fltheadstr *fp)
56 double mobcost,ceil(double);
60 if (sp->shp_effic > 0) {
61 mobcost = sp->shp_effic * sp->shp_speed * 0.01;
62 mobcost = 480.0 / ( mobcost*(1 + (50+sp->shp_tech)/
63 (double)(200+sp->shp_tech)));
65 /* the next two lines are not necessary since shp_mobquota is unsigned
66 and therefore cannot be less than 0.
67 if (sp->shp_mobquota<0)
73 howfar = (int)sp->shp_mobil - (int)sp->shp_mobquota;
74 howfar = ceil((howfar / mobcost));
80 "Ship #%d can move %d spaces on mobility %d (cost/sect %f)\n",
81 sp->shp_uid, howfar, sp->shp_mobil, mobcost);
83 if ((unsigned int)howfar < fp->maxmoves)
84 fp->maxmoves = howfar;
86 ep->mobil = sp->shp_mobil;
87 ep->mobcost = mobcost;
91 sail_find_fleet(struct fltheadstr **head, struct shpstr *sp)
93 struct fltheadstr *fltp;
95 struct fltelemstr *this;
106 /* If this ship is following, find the head of the follow list. */
107 for (ap=sp; ap; len++, ap=getshipp(follow)) {
108 follow = ap->shp_follow;
110 if (ap->shp_own != sp->shp_own) {
112 "Ship #%d, following #%d, which you don't own.\n",
113 sp->shp_uid, ap->shp_uid);
116 /* Not a follower. */
117 if (ap->shp_path[0] != 'f')
119 /* Following itself */
120 if (follow==ap->shp_uid ||
126 "Ship #%d, following #%d, which you don't own.\n",
127 sp->shp_uid, follow);
131 /* This should prevent infinite loops. */
134 "Ship #%d, too many follows (circular follow?).\n",
139 for (stop=0,cp=ap->shp_path; (!stop) && (*cp); cp++) {
155 /* we found a non-valid char in the path. */
157 wu(0,ap->shp_own, "invalid char '\\%03o' in path of ship %d\n",
158 (unsigned char)*cp, ap->shp_uid);
162 /* if this ship is not sailing anywhere then ignore it. */
166 /* Find the fleet structure we belong to. */
167 for (fltp=(*head); (fltp && fltp->leader != follow); fltp = fltp->next)
171 fltp = (struct fltheadstr *) malloc(sizeof(*fltp));
172 bzero((s_char *)fltp, sizeof(*fltp));
175 fltp->next = (*head);
178 /* Set the leader. */
179 fltp->leader = ap->shp_uid;
180 fltp->real_q = LEADER_REAL;
183 fltp->own = ap->shp_own;
184 fltp->maxmoves = 500;
187 /* If the fleet is not in the same sector as us, no go. */
188 if ( ( fltp->x!=sp->shp_x ) || ( fltp->y!=sp->shp_y ) ) {
190 "Ship %d not in same sector as its sailing fleet\n",
192 fltp->real_q = LEADER_WRONGSECT;
196 this = (struct fltelemstr *) malloc(sizeof(*this));
197 bzero((s_char *)this, sizeof(*this));
198 this->num = sp->shp_uid;
199 this->own = sp->shp_own;
200 this->next = fltp->head;
202 cost_ship(sp, this, fltp);
208 sail_nav_fleet(struct fltheadstr *fltp)
210 struct fltelemstr *fe;
211 struct shpstr *sp, ship;
213 struct sctstr *sectp;
217 struct emp_qelem ship_list;
221 switch (fltp->real_q) {
228 case LEADER_WRONGSECT:
235 "Fleet lead by %d is %s, can go %d spaces\n contains ships:",
236 fltp->leader, s, fltp->maxmoves);
237 for (fe=fltp->head; fe; fe = fe->next)
238 wu(0, fltp->own, " %d", fe->num);
239 wu(0, fltp->own, "\n");
241 sectp = getsectp(fltp->x, fltp->y);
242 switch (check_nav(sectp)) {
245 case CN_CONSTRUCTION:
248 wu(0,fltp->own, "Your fleet lead by %d is trapped by land.\n",
252 for (fe=fltp->head; fe; fe = fe->next) {
253 sp = getshipp(fe->num);
254 getvec(VT_ITEM, vec, (s_char *)sp, EF_SHIP);
255 if (vec[I_MILIT]==0 && vec[I_CIVIL]==0) {
257 " ship #%d (%s) is crewless and can't go on\n",
258 fe->num, cname(fe->own));
264 sp = getshipp(fltp->leader);
266 fltp_to_list(fltp, &ship_list); /* hack -KHS 1995 */
267 for (s=sp->shp_path; (*s) && (fltp->maxmoves>0); s++) {
268 dir = chkdir(*s, DIR_STOP, DIR_LAST);
269 if (0 != (error = shp_nav_one_sector(&ship_list, dir, own, 0)))
273 shp_put(&ship_list, own);
274 getship(sp->shp_uid, &ship);
275 fltp->x = ship.shp_x;
276 fltp->y = ship.shp_y;
277 for (p=&ship.shp_path[0]; *s; p++,s++)
280 putship(ship.shp_uid, &ship);
282 if (sp->shp_path[0]) {
284 "Fleet lead by #%d nav'd to %s, path left = %s\n",
285 fltp->leader, xyas(fltp->x,fltp->y,fltp->own),
289 "Fleet lead by #%d nav'd to %s, finished.\n",
290 fltp->leader, xyas(fltp->x,fltp->y,fltp->own));
291 wu(0,sp->shp_own, "Ship #%d has %d mobility now.\n",
292 fe->num, (int)fe->mobil);
301 struct fltheadstr *head=0;
302 struct fltheadstr *fltp;
306 for (n=0; NULL != (sp = getshipp(n)); n++) if (sp->shp_own==cn) {
307 sail_find_fleet(&head, sp);
310 /* see what the fleets fall out into */
311 for (fltp=head; fltp; fltp = fltp->next) {
312 sail_nav_fleet(fltp);
313 wu(0,fltp->own, "Your fleet lead by ship #%d has reached %s.\n",
314 fltp->leader,xyas(fltp->x,fltp->y,fltp->own));
317 /* Free up the memory, 'cause I want to. */
318 for (fltp=head; fltp!=0; ) {
319 struct fltelemstr *fe;
320 struct fltheadstr *saveh;
322 for (fe=fltp->head; fe!=0; ) {
323 struct fltelemstr *saveel;
333 /* The following is a total hack by Ken Stevens to cut down dramatically on repeated code 1995 */
336 fltp_to_list(struct fltheadstr *fltp, struct emp_qelem *list)
338 struct fltelemstr *fe;
343 for (fe=fltp->head; fe; fe = fe->next) {
344 mlp = (struct mlist *) malloc(sizeof(struct mlist));
345 sp = getshipp(fe->num);
346 mlp->mcp = mchr + sp->shp_type;
347 bcopy((s_char *)sp, (s_char *)&mlp->ship,
348 sizeof(struct shpstr));
349 mlp->mobil = fe->mobil;
350 emp_insque(&mlp->queue, list);