2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2013, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure, Markus Armbruster
6 * Empire 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 3 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, see <http://www.gnu.org/licenses/>.
21 * See files README, COPYING and CREDITS in the root of the source
22 * tree for related information and legal notices. It is expected
23 * that future projects/authors will amend these files as needed.
27 * sail.c: Sail ships during the update
29 * Known contributors to this file:
33 * Steve McClure, 1998-2000
48 double mobil, mobcost;
49 struct fltelemstr *next;
55 /* defines for the real_q member */
56 #define LEADER_VIRTUAL 0
58 #define LEADER_WRONGSECT 2
62 struct fltelemstr *head;
63 struct fltheadstr *next;
66 static void fltp_to_list(struct fltheadstr *, struct emp_qelem *);
69 cost_ship(struct shpstr *sp, struct fltelemstr *ep, struct fltheadstr *fp)
71 double mobcost = shp_mobcost(sp);
76 howfar = (int)sp->shp_mobil - (int)sp->shp_mobquota;
77 howfar = ceil((howfar / mobcost));
83 "Ship #%d can move %d spaces on mobility %d (cost/sect %f)\n",
84 sp->shp_uid, howfar, sp->shp_mobil, mobcost);
86 if ((unsigned)howfar < fp->maxmoves)
87 fp->maxmoves = howfar;
89 ep->mobil = sp->shp_mobil;
90 ep->mobcost = mobcost;
94 sail_find_fleet(struct fltheadstr **head, struct shpstr *sp)
96 struct fltheadstr *fltp;
98 struct fltelemstr *this;
104 if (sp->shp_own == 0)
109 /* If this ship is following, find the head of the follow list. */
110 for (ap = sp; ap; len++, ap = getshipp(follow)) {
111 follow = ap->shp_follow;
113 if (ap->shp_own != sp->shp_own) {
115 "Ship #%d, following #%d, which you don't own.\n",
116 sp->shp_uid, ap->shp_uid);
119 /* Not a follower. */
120 if (ap->shp_path[0] != 'f')
122 /* Following itself */
123 if (follow == ap->shp_uid || follow == sp->shp_uid)
128 "Ship #%d, following #%d, which you don't own.\n",
129 sp->shp_uid, follow);
133 /* This should prevent infinite loops. */
136 "Ship #%d, too many follows (circular follow?).\n",
141 for (stop = 0, cp = ap->shp_path; !stop && *cp; cp++) {
157 /* we found a non-valid char in the path. */
159 wu(0, ap->shp_own, "invalid char '\\%03o' in path of ship %d\n",
160 (unsigned char)*cp, ap->shp_uid);
164 /* if this ship is not sailing anywhere then ignore it. */
168 /* Find the fleet structure we belong to. */
169 for (fltp = *head; fltp && fltp->leader != follow; fltp = fltp->next) ;
172 fltp = malloc(sizeof(*fltp));
173 memset(fltp, 0, sizeof(*fltp));
179 /* Set the leader. */
180 fltp->leader = ap->shp_uid;
181 fltp->real_q = LEADER_REAL;
184 fltp->own = ap->shp_own;
185 fltp->maxmoves = 500;
188 /* If the fleet is not in the same sector as us, no go. */
189 if ((fltp->x != sp->shp_x) || (fltp->y != sp->shp_y)) {
191 "Ship %d not in same sector as its sailing fleet\n",
193 fltp->real_q = LEADER_WRONGSECT;
197 this = malloc(sizeof(*this));
198 memset(this, 0, sizeof(*this));
199 this->num = sp->shp_uid;
200 this->own = sp->shp_own;
201 this->next = fltp->head;
203 cost_ship(sp, this, fltp);
209 sail_nav_fleet(struct fltheadstr *fltp)
211 struct fltelemstr *fe;
212 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 for (fe = fltp->head; fe; fe = fe->next) {
243 sp = getshipp(fe->num);
244 if (sp->shp_item[I_MILIT] == 0 && sp->shp_item[I_CIVIL] == 0) {
246 " ship #%d (%s) is crewless and can't go on\n",
247 fe->num, cname(fe->own));
250 if ((shp_check_nav(sectp, sp) == CN_LANDLOCKED) &&
251 (dchr[sectp->sct_type].d_nav == NAV_CANAL)) {
253 "Your ship #%d (%s) is too big to fit through the canal.\n",
254 fe->num, cname(fe->own));
260 sp = getshipp(fltp->leader);
261 sectp = getsectp(fltp->x, fltp->y);
262 if (shp_check_nav(sectp, sp) != CN_NAVIGABLE)
263 wu(0, fltp->own, "Your fleet lead by %d is trapped by land.\n",
265 sp = getshipp(fltp->leader);
267 fltp_to_list(fltp, &ship_list); /* hack -KHS 1995 */
268 for (s = sp->shp_path; *s && fltp->maxmoves > 0; s++) {
270 if (0 != shp_nav_one_sector(&ship_list, dir, own, 0))
274 unit_put(&ship_list, own);
275 getship(sp->shp_uid, &ship);
276 fltp->x = ship.shp_x;
277 fltp->y = ship.shp_y;
278 for (p = &ship.shp_path[0]; *s; p++, s++)
281 putship(ship.shp_uid, &ship);
283 if (sp->shp_path[0]) {
285 "Fleet lead by #%d nav'd to %s, path left = %s\n",
286 fltp->leader, xyas(fltp->x, fltp->y, fltp->own), &sp->shp_path);
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 = NULL;
302 struct fltheadstr *fltp;
306 for (n = 0; NULL != (sp = getshipp(n)); n++)
307 if (sp->shp_own == cn) {
308 sail_find_fleet(&head, sp);
311 /* see what the fleets fall out into */
312 for (fltp = head; fltp; fltp = fltp->next) {
313 if (sail_nav_fleet(fltp))
314 wu(0, fltp->own, "Your fleet lead by ship #%d has reached %s.\n",
315 fltp->leader, xyas(fltp->x, fltp->y, fltp->own));
318 /* Free up the memory, 'cause I want to. */
319 for (fltp = head; fltp;) {
320 struct fltelemstr *fe;
321 struct fltheadstr *saveh;
323 for (fe = fltp->head; fe;) {
324 struct fltelemstr *saveel;
334 /* The following is a total hack by Ken Stevens to cut down dramatically on repeated code 1995 */
337 fltp_to_list(struct fltheadstr *fltp, struct emp_qelem *list)
339 struct fltelemstr *fe;
344 for (fe = fltp->head; fe; fe = fe->next) {
345 mlp = malloc(sizeof(struct ulist));
346 sp = getshipp(fe->num);
347 mlp->chrp = (struct empobj_chr *)(mchr + sp->shp_type);
348 mlp->unit.ship = *sp;
349 ef_mark_fresh(EF_SHIP, &mlp->unit.ship);
350 mlp->mobil = fe->mobil;
351 emp_insque(&mlp->queue, list);