]> git.pond.sub.org Git - empserver/blob - src/lib/commands/orde.c
Clean up dead code in orde()
[empserver] / src / lib / commands / orde.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2010, 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  *  orde.c: Turn on/off autonavigation
29  *
30  *  Known contributors to this file:
31  *     Chad Zabel, 1994
32  *     Steve McClure, 2000
33  */
34
35 #include <config.h>
36
37 #include "commands.h"
38 #include "item.h"
39 #include "optlist.h"
40 #include "path.h"
41 #include "ship.h"
42
43 /*
44  *  Command syntax:
45  *
46  *  ORDER <ship>                                  Show orders
47  *  ORDER <ship> c[ancel]                         Cancel orders
48  *  ORDER <ship> s[top]                           Suspend orders
49  *  ORDER <ship> r[esume]                         Resume orders
50  *  ORDER <ship> d[eclare] <dest1>                Set destination
51  *               d[eclare] <dest1> <dest2>
52  *  ORDER <ship> l[evel]   <field> <start/end> <comm> <level>
53  *
54  * New syntax:
55  *  qorder <ship>    display cargo levels
56  *  sorder <ship>    display statistical info
57  */
58
59 int
60 orde(void)
61 {
62     int sub, level;
63     int scuttling = 0;
64     struct nstr_item nb;
65     struct shpstr ship;
66     struct shpstr start;        /* Used for checking database */
67     struct ichrstr *i1;
68     coord p0x, p0y, p1x, p1y;
69     int i;
70     char *p, *p1, *dest;
71     char buf1[128];
72     char buf[1024];
73     char prompt[128];
74
75     if (!snxtitem(&nb, EF_SHIP, player->argp[1], NULL))
76         return RET_SYN;
77     while (!player->aborted && nxtitem(&nb, (&ship))) {
78         if (!player->owner || ship.shp_own == 0)
79             continue;
80         if (opt_SAIL) {
81             if (*ship.shp_path) {
82                 pr("Ship #%d has a \"sail\" path!\n", ship.shp_uid);
83                 continue;
84             }
85         }
86         memcpy(&start, &ship, sizeof(struct shpstr));
87         sprintf(prompt,
88                 "Ship #%d, declare, cancel, suspend, resume, level? ",
89                 ship.shp_uid);
90         p = getstarg(player->argp[2], prompt, buf);
91         if (player->aborted || !p || !*p)
92             return RET_FAIL;
93         switch (*p) {
94         default:
95             pr("Bad order type!\n");
96             return RET_SYN;
97         case 'c':               /* clear ship fields  */
98             ship.shp_mission = 0;
99             ship.shp_autonav &= ~(AN_AUTONAV + AN_STANDBY + AN_LOADING);
100             for (i = 0; i < TMAX; i++) {
101                 ship.shp_tstart[i] = I_NONE;
102                 ship.shp_tend[i] = I_NONE;
103                 ship.shp_lstart[i] = 0;
104                 ship.shp_lend[i] = 0;
105             }
106             break;
107         case 's':               /* suspend ship movement  */
108             ship.shp_mission = 0;
109             ship.shp_autonav |= AN_STANDBY;
110             break;
111         case 'r':               /* resume ship movement   */
112             ship.shp_mission = 0;
113             ship.shp_autonav &= ~AN_STANDBY;
114             break;
115         case 'd':               /* declare path */
116             scuttling = 0;
117             /* Need location */
118             p = getstarg(player->argp[3], "Destination? ", buf);
119             if (!p || !*p)
120                 return RET_SYN;
121             if (!sarg_xy(p, &p0x, &p0y))
122                 return RET_SYN;
123             p1x = p0x;
124             p1y = p0y;
125
126             p = getstarg(player->argp[4], "Second dest? ", buf);
127             if (!p)
128                 return RET_FAIL;
129             if (!*p || !strcmp(p, "-")) {
130                 pr("A one-way order has been accepted.\n");
131             } else if (!strncmp(p, "s", 1)) {
132                 if (opt_TRADESHIPS) {
133                     if (!(mchr[(int)ship.shp_type].m_flags & M_TRADE)) {
134                         pr("You can't auto-scuttle that ship!\n");
135                         return RET_SYN;
136                     }
137                 } else {
138                     pr("You can't auto-scuttle that ship!\n");
139                     return RET_SYN;
140                 }
141                 pr("A scuttle order has been accepted.\n");
142                 scuttling = 1;
143             } else {
144                 if (!sarg_xy(p, &p1x, &p1y))
145                     return RET_SYN;
146                 pr("A circular order has been accepted.\n");
147             }
148
149             /*
150              *  Set new destination and trade type fields.
151              */
152             ship.shp_mission = 0;
153             ship.shp_destx[1] = p1x;
154             ship.shp_desty[1] = p1y;
155             ship.shp_destx[0] = p0x;
156             ship.shp_desty[0] = p0y;
157
158             ship.shp_autonav &= ~(AN_STANDBY | AN_LOADING);
159             ship.shp_autonav |= AN_AUTONAV;
160
161             if (scuttling)
162                 ship.shp_autonav |= AN_SCUTTLE;
163             break;
164
165             /* set cargo levels on the ship */
166
167         case 'l':
168             /* convert player->argp[3] to an integer */
169             if (player->argp[3])
170                 sub = atoi(player->argp[3]);
171             else {
172                 sprintf(buf1, "Field (1-%d) ", TMAX);
173                 if (!getstarg(player->argp[3], buf1, buf))
174                     return RET_SYN;
175                 sub = atoi(buf);
176             }
177             /* check to make sure value in within range. */
178             if (sub > TMAX || sub < 1) {
179                 pr("Value must range from 1 to %d\n", TMAX);
180                 break;
181             }
182
183             /* to keep sub in range of our arrays
184                subtract 1 so the new range is 0-(TMAX-1)
185              */
186             sub = sub - 1;;
187
188             if (ship.shp_autonav & AN_AUTONAV) {
189                 dest = getstarg(player->argp[4], "Start or End? ", buf);
190                 if (!dest)
191                     break;
192                 switch (*dest) {
193                 default:
194                     pr("You must enter 'start' or 'end'\n");
195                     return RET_SYN;
196                 case 'e':
197                 case 'E':
198                     i1 = whatitem(player->argp[5], "Commodity? ");
199                     if (!i1)
200                         break;
201                     p1 = getstarg(player->argp[6], "Amount? ",
202                                   buf);
203                     if (!p1)
204                         return RET_SYN;
205                     level = atoi(p1);
206                     if (level < 0) {
207                         level = 0;      /* prevent negatives. */
208                         pr("You must use positive number! Level set to 0.\n");
209                     }
210                     ship.shp_tstart[sub] = i1->i_uid;
211                     ship.shp_lstart[sub] = level;
212                     pr("Order Set \n");
213                     break;
214                 case 's':
215                 case 'S':
216                     i1 = whatitem(player->argp[5], "Commodity? ");
217                     if (!i1)
218                         break;
219                     p1 = getstarg(player->argp[6], "Amount? ",
220                                   buf);
221                     if (!p1)
222                         return RET_SYN;
223                     level = atoi(p1);
224                     if (level < 0) {
225                         level = 0;
226                         pr("You must use positive number! Level set to 0.\n");
227                     }
228                     ship.shp_tend[sub] = i1->i_uid;
229                     ship.shp_lend[sub] = level;
230                     pr("Order Set \n");
231                     break;
232                 }
233             } else
234                 pr("You need to 'declare' a ship path first, see 'info order'\n");
235
236             break;
237         }                       /* end of switch (*p) */
238
239
240
241         /*
242          *  Set loading flag if ship is already in one
243          *  of the specified harbors and a cargo has been
244          *  specified.
245          */
246
247         if (((ship.shp_x == ship.shp_destx[0])
248              && (ship.shp_y == ship.shp_desty[0])
249              && (ship.shp_lstart[0] != ' '))
250             || ((ship.shp_x == ship.shp_desty[1])
251                 && (ship.shp_y == ship.shp_desty[1])
252                 && (ship.shp_lstart[1] != ' '))) {
253
254             coord tcord;
255             i_type tcomm;
256             short lev[TMAX];
257             int i;
258
259             ship.shp_autonav |= AN_LOADING;
260
261             /*  swap variables, this keeps
262                the load_it() procedure happy. CZ
263              */
264             tcord = ship.shp_destx[0];
265             ship.shp_destx[0] = ship.shp_destx[1];
266             ship.shp_destx[1] = tcord;
267             tcord = ship.shp_desty[0];
268             ship.shp_desty[0] = ship.shp_desty[1];
269             ship.shp_desty[1] = tcord;
270
271             for (i = 0; i < TMAX; i++) {
272                 lev[i] = ship.shp_lstart[i];
273                 ship.shp_lstart[i] = ship.shp_lend[i];
274                 ship.shp_lend[i] = lev[i];
275                 tcomm = ship.shp_tstart[i];
276                 ship.shp_tstart[i] = ship.shp_tend[i];
277                 ship.shp_tend[i] = tcomm;
278             }
279         }
280         /*
281            **  Write ship back to database, then give it
282            **  a kick down the autonav route if necessary.
283          */
284
285
286         /* Now do a sanity check. */
287         if (!check_ship_ok(&start))
288             return RET_SYN;
289
290         putship(ship.shp_uid, &ship);
291     }
292     return RET_OK;
293 }
294
295 static void
296 eta_calc(struct shpstr *sp, char *path, int *len, int *nupdates)
297 {
298     double mobcost, mobil;
299     int i;
300
301     i = strlen(path);
302     *len = i;
303     *nupdates = 1;
304
305     mobcost = shp_mobcost(sp);
306     mobil = sp->shp_mobil;
307     while (i) {
308         if (mobil > 0) {
309             mobil -= mobcost;
310             i--;
311         } else {
312             mobil += (ship_mob_scale * (float)etu_per_update);
313             (*nupdates)++;
314         }
315     }
316 }
317
318 static void
319 prhold(int hold, i_type itype, int amt)
320 {
321     if (itype != I_NONE && amt != 0) {
322         if (CANT_HAPPEN(itype <= I_NONE || itype > I_MAX))
323             return;
324         pr("%d-", hold + 1);
325         pr("%c", ichr[itype].i_mnem);
326         pr(":");
327         pr("%d ", amt);
328     }
329 }
330
331 int
332 qorde(void)
333 {
334     int nships = 0;
335     int i;
336     struct nstr_item nb;
337     struct shpstr ship;
338
339     if (!snxtitem(&nb, EF_SHIP, player->argp[1], NULL))
340         return RET_SYN;
341     while (nxtitem(&nb, (&ship))) {
342         if (!player->owner || ship.shp_own == 0)
343             continue;
344         if (!(ship.shp_autonav & AN_AUTONAV)
345             && (!opt_SAIL || !ship.shp_path[0]))
346             continue;
347
348         if (!nships) {          /* 1st ship, print banner */
349             if (player->god)
350                 pr("own ");
351             pr("shp#     ship type    ");
352             pr("[Starting]       (Ending)    \n");
353         }
354         nships++;
355         if (player->god)
356             pr("%3d ", ship.shp_own);
357         pr("%4d", nb.cur);
358         pr(" %-16.16s", mchr[(int)ship.shp_type].m_name);
359
360         if (ship.shp_autonav & AN_AUTONAV) {
361             pr(" [");
362             for (i = 0; i < TMAX; i++)
363                 prhold(i, ship.shp_tend[i], ship.shp_lend[i]);
364             pr("] , (");
365             for (i = 0; i < TMAX; i++)
366                 prhold(i, ship.shp_tstart[i], ship.shp_lstart[i]);
367             pr(")");
368             if (ship.shp_autonav & AN_SCUTTLE)
369                 pr(" scuttling");
370             pr("\n");
371         } else
372             pr(" has a sail path\n");
373
374         if (ship.shp_name[0] != 0) {
375             if (player->god)
376                 pr("    ");
377             pr("       %s\n", ship.shp_name);
378         }
379     }
380     if (!nships) {
381         if (player->argp[1])
382             pr("%s: No ship(s)\n", player->argp[1]);
383         else
384             pr("%s: No ship(s)\n", "");
385         return RET_FAIL;
386     } else
387         pr("%d ship%s\n", nships, splur(nships));
388     return RET_OK;
389 }
390
391 int
392 sorde(void)
393 {
394     int nships = 0;
395     int len, updates;
396     char *c;
397     struct nstr_item nb;
398     struct shpstr ship;
399     char buf[1024];
400
401     if (!snxtitem(&nb, EF_SHIP, player->argp[1], NULL))
402         return RET_SYN;
403     while (nxtitem(&nb, (&ship))) {
404         if (!player->owner || ship.shp_own == 0)
405             continue;
406         if (!(ship.shp_autonav & AN_AUTONAV)
407             && (!opt_SAIL || !ship.shp_path[0]))
408             continue;
409
410         if (!nships) {          /* 1st ship, print banner */
411             if (player->god)
412                 pr("own ");
413             pr("shp#     ship type      x,y    ");
414             pr("start    end   ");
415             pr("len  eta\n");
416         }
417         nships++;
418         if (player->god)
419             pr("%3d ", ship.shp_own);
420         pr("%4d", nb.cur);
421         pr(" %-16.16s", mchr[(int)ship.shp_type].m_name);
422         prxy(" %3d,%-3d", ship.shp_x, ship.shp_y, player->cnum);
423
424         if (ship.shp_autonav & AN_AUTONAV) {
425             /* Destination 1 */
426             prxy(" %3d,%-3d",
427                  ship.shp_destx[1], ship.shp_desty[1], player->cnum);
428
429             /* Destination 2 */
430             if ((ship.shp_destx[1] != ship.shp_destx[0])
431                 || (ship.shp_desty[1] != ship.shp_desty[0])) {
432                 prxy(" %3d,%-3d",
433                      ship.shp_destx[0], ship.shp_desty[0], player->cnum);
434             } else
435                 pr("        ");
436
437             if (ship.shp_autonav & AN_STANDBY)
438                 pr(" suspended");
439             else if (ship.shp_autonav & AN_LOADING)
440                 pr(" loading");
441             else {
442                 /* ETA calculation */
443
444                 c = BestShipPath(buf, ship.shp_x, ship.shp_y,
445                                  ship.shp_destx[0], ship.shp_desty[0],
446                                  ship.shp_own);
447                 if (!c)
448                     pr(" no route possible");
449                 else if (*c == 'h')
450                     pr(" has arrived");
451                 else {
452                     /* distance to destination */
453                     eta_calc(&ship, c, &len, &updates);
454                     pr(" %3d %4d", len, updates);
455                 }
456             }
457             if (ship.shp_autonav & AN_SCUTTLE)
458                 pr(" (scuttling)");
459             pr("\n");
460         } else
461             pr(" has a sail path\n");
462
463         if (ship.shp_name[0] != 0) {
464             if (player->god)
465                 pr("    ");
466             pr("       %s\n", ship.shp_name);
467         }
468     }
469     if (!nships) {
470         if (player->argp[1])
471             pr("%s: No ship(s)\n", player->argp[1]);
472         else
473             pr("%s: No ship(s)\n", "");
474         return RET_FAIL;
475     } else
476         pr("%d ship%s\n", nships, splur(nships));
477     return RET_OK;
478 }