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