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