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