Varargs cleanup is almost finished.
[vms-empire.git] / edit.c
1 /*
2  *    Copyright (C) 1987, 1988 Chuck Simmons
3  * 
4  * See the file COPYING, distributed with empire, for restriction
5  * and warranty information.
6  */
7
8 /*
9 edit.c -- Routines to handle edit mode commands.
10 */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <curses.h>
15 #include <ctype.h>
16 #include "empire.h"
17 #include "extern.h"
18
19 void e_move(loc_t *path_start, loc_t loc);
20 extern int get_piece_name(void);
21
22 void
23 edit(loc_t edit_cursor)
24 {
25         char e_cursor();
26         void e_leave(), e_print(), e_random();
27         void e_stasis(), e_end(), e_wake(), e_sleep();
28         void e_info(), e_prod(), e_help(), e_explore();
29         void e_fill(), e_land(), e_city_func(), e_transport();
30         void e_attack(), e_repair();
31
32         loc_t path_start;
33         int path_type;
34         char e;
35         
36         path_start = -1; /* not building a path yet */
37         
38         for (;;) { /* until user gives command to leave */
39                 display_loc_u (edit_cursor); /* position cursor */
40                 e = e_cursor (&edit_cursor); /* handle cursor movement */
41
42                 switch (e) {
43                 case 'B': /* change city production */
44                         e_prod (edit_cursor);
45                         break;
46                 case 'F': /* fill */
47                         e_fill (edit_cursor);
48                         break;
49                 case 'G': /* explore */
50                         e_explore (edit_cursor);
51                         break;
52                 case 'H': /* help */
53                         e_help ();
54                         break;
55                 case 'I': /* directional stasis */
56                         e_stasis (edit_cursor);
57                         break;
58                 case 'K': /* wake up anything and everything */
59                         e_wake (edit_cursor);
60                         break;
61                 case 'L': /* land plane */
62                         e_land (edit_cursor);
63                         break;
64                 case 'M': /* start move to location */
65                         path_type = NOPIECE;
66                         e_move (&path_start, edit_cursor);
67                         break;
68                 case 'N': /* end move to location */
69                         e_end (&path_start, edit_cursor, path_type);
70                         break;
71                 case 'O': /* leave display mode */
72                         e_leave ();
73                         return;
74                 case 'P': /* print new sector */
75                         e_print (&edit_cursor);
76                         break;
77                 case 'R': /* make piece move randomly */
78                         e_random (edit_cursor);
79                         break;
80                 case 'S': /* sleep */
81                         e_sleep (edit_cursor);
82                         break;
83                 case 'T': /* transport army */
84                         e_transport (edit_cursor);
85                         break;
86                 case 'U': /* repair ship */
87                         e_repair (edit_cursor);
88                         break;
89                 case 'V': /* set city function */
90                         e_city_func (&path_start, edit_cursor, &path_type);
91                         break;
92                 case 'Y': /* set army func to attack */
93                         e_attack (edit_cursor);
94                         break;
95                 case '?': /* request info */
96                         e_info (edit_cursor);
97                         break;
98                 case '\014': /* control-L */
99                         redraw ();
100                         break;
101                 default: /* bad command? */
102                         huh ();
103                         break;
104                 }
105         }
106 }
107
108 /*
109 Get the next command.  We handle cursor movement here.
110 This routine is an attempt to make cursor movement reasonably
111 fast.
112 */
113
114 char
115 e_cursor(loc_t *edit_cursor)
116 {
117         chtype e;
118         int p;
119         
120         /* set up terminal */
121         (void) crmode ();
122         (void) refresh ();
123         e = getch ();
124         topini (); /* clear any error messages */
125
126         for (;;) {
127                 p = direction (e);
128                 if (p == -1) break;
129
130                 if (!move_cursor (edit_cursor, dir_offset[p]))
131                         (void) beep ();
132                 
133                 (void) refresh ();
134                 e = getch ();
135         }
136         (void) nocrmode (); /* reset terminal */
137         return toupper(e);
138 }
139
140 /*
141 Leave edit mode.
142 */
143
144 void
145 e_leave(void) {
146 }
147
148 /*
149 Print new sector.
150 */
151
152 void
153 e_print(loc_t *edit_cursor)
154 {
155         int sector;
156         
157         sector = get_range ("New Sector? ", 0, NUM_SECTORS-1);
158
159         /* position cursor at center of sector */
160         *edit_cursor = sector_loc (sector);
161         sector_change (); /* allow change of sector */
162 }
163
164 /*
165 Set the function of a piece.
166 */
167
168 void
169 e_set_func(loc_t loc, long func)
170 {
171         piece_info_t *obj;
172         obj = find_obj_at_loc (loc);
173         if (obj != NULL && obj->owner == USER) {
174                 obj->func = func;
175                 return;
176         }
177         huh (); /* no object here */
178 }
179         
180 /* Set the function of a city for some piece. */
181
182 void
183 e_set_city_func(city_info_t *cityp, int type, long func)
184 {
185         cityp->func[type] = func;
186 }
187
188 /*
189 Set a piece to move randomly.
190 */
191
192 void
193 e_random(loc_t loc)
194 {
195         e_set_func (loc, RANDOM);
196 }
197
198 void
199 e_city_random(city_info_t *cityp, int type)
200 {
201         e_set_city_func (cityp, type, RANDOM);
202 }
203
204 /*
205 Put a ship in fill mode.
206 */
207
208 void
209 e_fill(loc_t loc)
210 {
211         if (user_map[loc].contents == 'T' || user_map[loc].contents == 'C')
212                 e_set_func (loc, FILL);
213         else huh ();
214 }
215
216 void
217 e_city_fill(city_info_t *cityp, int type)
218 {
219         if (type == TRANSPORT || type == CARRIER)
220                 e_set_city_func (cityp, type, FILL);
221         else huh ();
222 }
223
224 /*
225 Set a piece to explore.
226 */
227
228 void
229 e_explore(loc_t loc)
230 {
231         e_set_func (loc, EXPLORE);
232 }
233
234 void
235 e_city_explore(city_info_t *cityp, loc_t type)
236 {
237         e_set_city_func (cityp, type, EXPLORE);
238 }
239
240 /*
241 Set a fighter to land.
242 */
243
244 void
245 e_land(loc_t loc)
246 {
247         if (user_map[loc].contents == 'F')
248                 e_set_func (loc, LAND);
249         else huh ();
250 }
251
252 /*
253 Set an army's function to TRANSPORT.
254 */
255
256 void
257 e_transport(loc_t loc)
258 {
259         if (user_map[loc].contents == 'A')
260                 e_set_func (loc, WFTRANSPORT);
261         else huh ();
262 }
263
264 /*
265 Set an army's function to ATTACK.
266 */
267
268 void
269 e_attack(loc_t loc)
270 {
271         if (user_map[loc].contents == 'A')
272                 e_set_func (loc, ARMYATTACK);
273         else huh ();
274 }
275
276 void
277 e_city_attack(city_info_t *cityp, int type)
278 {
279         if (type == ARMY)
280                 e_set_city_func (cityp, type, ARMYATTACK);
281         else huh ();
282 }
283
284 /*
285 Set a ship's function to REPAIR.
286 */
287
288 void
289 e_repair(loc_t loc)
290 {
291         if (strchr ("PDSTBC", user_map[loc].contents))
292                 e_set_func (loc, REPAIR);
293         else huh ();
294 }
295
296 void
297 e_city_repair(city_info_t *cityp, int type)
298 {
299         if (type == ARMY || type == FIGHTER || type == SATELLITE)
300                 huh ();
301         else e_set_city_func (cityp, type, REPAIR);
302 }
303
304 /*
305 Set object to move in a direction.
306 */
307
308 static char dirs[] = "WEDCXZAQ";
309  
310 void
311 e_stasis(loc_t loc)
312 {
313         char e;
314         char *p;
315         
316         if (!isupper (user_map[loc].contents)) huh (); /* no object here */
317         else if (user_map[loc].contents == 'X') huh ();
318         else {
319                 e = get_chx(); /* get a direction */
320                 p = strchr (dirs, e);
321
322                 if (p == NULL) huh ();
323                 else e_set_func (loc, (long)(MOVE_N - (p - dirs)));
324         }
325 }
326
327 void
328 e_city_stasis(city_info_t *cityp, int type)
329 {
330         char e;
331         char *p;
332         
333         e = get_chx(); /* get a direction */
334         p = strchr (dirs, e);
335
336         if (p == NULL) huh ();
337         else e_set_city_func (cityp, type, (long)(MOVE_N - (p - dirs)));
338 }
339
340 /*
341 Wake up anything and everything.
342 */
343
344 void
345 e_wake(loc_t loc)
346 {
347         city_info_t *cityp;
348         piece_info_t *obj;
349         int i;
350
351         cityp = find_city (loc);
352         if (cityp != NULL) {
353                 for (i = 0; i < NUM_OBJECTS; i++)
354                         cityp->func[i] = NOFUNC;
355         }
356         for (obj = map[loc].objp; obj != NULL; obj = obj->loc_link.next)
357                 obj->func = NOFUNC;
358 }
359
360 void
361 e_city_wake(city_info_t *cityp, int type)
362 {
363         e_set_city_func (cityp, type, NOFUNC);
364 }
365
366 /*
367 Set a city's function.  We get the piece type to set, then
368 the function itself.
369 */
370
371 void
372 e_city_func(loc_t *path_start, loc_t loc, int *path_type)
373 {
374         int type;
375         char e;
376         city_info_t *cityp;
377
378         cityp = find_city (loc);
379         if (!cityp || cityp->owner != USER) {
380                 huh ();
381                 return;
382         }
383
384         type = get_piece_name();
385         if (type == NOPIECE) {
386                 huh ();
387                 return;
388         }
389         
390         e = get_chx ();
391         
392         switch (e) {
393         case 'F': /* fill */
394                 e_city_fill (cityp, type);
395                 break;
396         case 'G': /* explore */
397                 e_city_explore (cityp, type);
398                 break;
399         case 'I': /* directional stasis */
400                 e_city_stasis (cityp, type);
401                 break;
402         case 'K': /* turn off function */
403                 e_city_wake (cityp, type);
404                 break;
405         case 'M': /* start move to location */
406                 *path_type = type;
407                 e_move (path_start, loc);
408                 break;
409         case 'R': /* make piece move randomly */
410                 e_city_random (cityp, type);
411                 break;
412         case 'U': /* repair ship */
413                 e_city_repair (cityp, type);
414                 break;
415         case 'Y': /* set army func to attack */
416                 e_city_attack (cityp, type);
417                 break;
418         default: /* bad command? */
419                 huh ();
420                 break;
421         }
422 }
423
424 /*
425 Beginning of move to location.
426 */
427
428 void
429 e_move(loc_t *path_start, loc_t loc)
430 {
431         if (!isupper(user_map[loc].contents)) huh (); /* nothing there? */
432         else if (user_map[loc].contents == 'X') huh (); /* enemy city? */
433         else *path_start = loc;
434 }
435
436 /*
437 End of move to location.
438 */
439
440 void
441 e_end(loc_t *path_start, loc_t loc, int path_type)
442 {
443         city_info_t *cityp;
444         
445         if (*path_start == -1) huh (); /* no path started? */
446         else if (path_type == NOPIECE) e_set_func (*path_start, loc);
447         else {
448                 cityp = find_city (*path_start);
449                 ASSERT (cityp);
450                 e_set_city_func (cityp, path_type, loc);
451         }
452
453         *path_start = -1; /* remember no path in progress */
454 }
455
456 /*
457 Put a piece to sleep.
458 */
459
460 void
461 e_sleep(loc_t loc)
462 {
463         if (user_map[loc].contents == 'O') huh (); /* can't sleep a city */
464         else e_set_func (loc, SENTRY);
465 }
466
467 /*
468 Print out information about a piece.
469 */
470
471 void
472 e_info(loc_t edit_cursor)
473 {
474         void e_city_info(loc_t), e_piece_info(loc_t edit_cursor, char ab);
475
476         char ab;
477
478         ab = user_map[edit_cursor].contents;
479
480         if (ab == 'O') e_city_info (edit_cursor);
481         else if (ab == 'X' && debug) e_city_info (edit_cursor);
482         else if ((ab >= 'A') && (ab <= 'T'))
483                 e_piece_info (edit_cursor, ab);
484         else if ((ab >= 'a') && (ab <= 't') && (debug))
485                 e_piece_info (edit_cursor, ab);
486         else huh ();
487 }
488
489 /*
490 Print info about a piece.
491 */
492
493 void
494 e_piece_info(loc_t edit_cursor, char ab)
495 {
496         piece_info_t *obj;
497         int type;
498         char *p;
499
500         ab = toupper (ab);
501         p = strchr (type_chars, ab);
502         type = p - type_chars;
503
504         obj = find_obj (type, edit_cursor);
505         ASSERT (obj != NULL);
506         describe_obj (obj);
507 }
508
509 /*
510 Display info on a city.
511 */
512
513 void
514 e_city_info(loc_t edit_cursor)
515 {
516         piece_info_t *obj;
517         city_info_t *cityp;
518         int f, s;
519         char func_buf[STRSIZE];
520         char temp_buf[STRSIZE];
521         char junk_buf2[STRSIZE];
522
523         error (0,0,0,0,0,0,0,0,0); /* clear line */
524
525         f = 0; /* no fighters counted yet */
526         for (obj = map[edit_cursor].objp; obj != NULL;
527                 obj = obj->loc_link.next)
528                         if (obj->type == FIGHTER) f++;
529
530         s = 0; /* no ships counted yet */
531         for (obj = map[edit_cursor].objp; obj != NULL;
532                 obj = obj->loc_link.next)
533                         if (obj->type >= DESTROYER) s++;
534
535         if (f == 1 && s == 1) 
536                 (void) sprintf (jnkbuf, "1 fighter landed, 1 ship docked");
537         else if (f == 1)
538                 (void) sprintf (jnkbuf, "1 fighter landed, %d ships docked", s);
539         else if (s == 1)
540                 (void) sprintf (jnkbuf, "%d fighters landed, 1 ship docked", f);
541         else (void) sprintf (jnkbuf, "%d fighters landed, %d ships docked", f, s);
542
543         cityp = find_city (edit_cursor);
544         ASSERT (cityp != NULL);
545
546         *func_buf = 0; /* nothing in buffer */
547         for (s = 0; s < NUM_OBJECTS; s++) { /* for each piece */
548                 if (cityp->func[s] < 0)
549                         (void) sprintf (temp_buf, "%c:%s; ",
550                                 piece_attr[s].sname,
551                                 func_name[FUNCI(cityp->func[s])]);
552                 else (void) sprintf (temp_buf, "%c: %d;",
553                                 piece_attr[s].sname,
554                                 loc_disp(cityp->func[s]));
555                 
556                 (void) strcat (func_buf, temp_buf);
557         }
558
559         (void) sprintf (junk_buf2,
560                 "City at location %d will complete %s on round %ld",
561                 loc_disp(cityp->loc),
562                 piece_attr[(int)cityp->prod].article,
563                 date + piece_attr[(int)cityp->prod].build_time - cityp->work);
564
565         info (junk_buf2, jnkbuf, func_buf);
566 }
567
568 /*
569 Change city production.
570 */
571
572 void
573 e_prod(loc_t loc)
574 {
575         city_info_t *cityp;
576         
577         cityp = find_city (loc);
578
579         if (cityp == NULL) huh (); /* no city? */
580         else set_prod (cityp);
581 }
582
583 /*
584 get help
585 */
586
587 void
588 e_help(void) {
589         help (help_edit, edit_lines);
590         prompt ("Press any key to continue: ",0,0,0,0,0,0,0,0);
591         (void) get_chx ();
592 }