5de081916c4716c48a4fb5b0f74492bb3646693a
[super-star-trek.git] / io.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <termios.h>
4 #include <curses.h>
5 #include <signal.h>
6 #include <ctype.h>
7 #include <stdarg.h>
8
9 #include "sst.h"
10 #include "sstlinux.h"
11
12 static int linecount;   /* for paging */
13
14 WINDOW *curwnd;
15
16 static void outro(void)
17 /* wrap up, either normally or due to signal */
18 {
19     if (game.options & OPTION_CURSES) {
20         clear();
21         curs_set(1);
22         (void)refresh();
23         (void)resetterm();
24         //(void)echo();
25         (void)endwin();
26         putchar('\n');
27     }
28 }
29
30 void iostart(void) 
31 {
32     if (game.options & OPTION_CURSES) {
33
34         if (atexit(outro)){
35             fprintf(stderr,"Unable to register outro(), exiting...\n");
36             exit(1);
37         }
38         (void)initscr();
39 #ifdef KEY_MIN
40         keypad(stdscr, TRUE);
41 #endif /* KEY_MIN */
42         (void)saveterm();
43         (void)nonl();
44         (void)cbreak();
45 #ifdef A_COLOR
46         {
47         start_color();
48         init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
49         init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
50         init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
51         init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
52         init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
53         init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
54         init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
55         init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
56         }
57 #endif /* A_COLOR */
58         //(void)noecho();
59         fullscreen_window = stdscr;
60         srscan_window     = newwin(12, 25, 0,       0);
61         report_window     = newwin(10, 0,  1,       25);
62         lrscan_window     = newwin(10, 0,  0,       64); 
63         message_window    = newwin(0,  0,  12,      0);
64         prompt_window     = newwin(1,  0,  LINES-2, 0); 
65         scrollok(message_window, TRUE);
66         setwnd(fullscreen_window);
67         textcolor(DEFAULT);
68     }
69 }
70
71
72 void waitfor(void)
73 /* wait for user action -- OK to do nothing if on a TTY */
74 {
75     if (game.options & OPTION_CURSES)
76         getch();
77 }
78
79 void pause_game(int i) 
80 {
81     char *prompt;
82     char buf[BUFSIZ];
83     if (i==1) {
84         if (skill > SKILL_FAIR)
85             prompt = "[ANOUNCEMENT ARRIVING...]";
86         else
87             prompt = "[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]";
88     }
89     else {
90         if (skill > SKILL_FAIR)
91             prompt = "[CONTINUE?]";
92         else
93             prompt = "[PRESS ENTER TO CONTINUE]";
94
95     }
96     if (game.options & OPTION_CURSES) {
97         drawmaps(0);
98         setwnd(prompt_window);
99         wclear(prompt_window);
100         waddstr(prompt_window, prompt);
101         wgetnstr(prompt_window, buf, sizeof(buf));
102         wclear(prompt_window);
103         wrefresh(prompt_window);
104         setwnd(message_window);
105     } else {
106         putchar('\n');
107         proutn(prompt);
108         fgets(buf, sizeof(buf), stdin);
109         if (i != 0) {
110             int j;
111             for (j = 0; j < 24; j++)
112                 putchar('\n');
113         }
114         linecount = 0;
115     }
116 }
117
118
119 void skip(int i) 
120 {
121     while (i-- > 0) {
122         if (game.options & OPTION_CURSES) {
123             proutn("\n\r");
124         } else {
125             linecount++;
126             if (linecount >= 24)
127                 pause_game(0);
128             else
129                 putchar('\n');
130         }
131     }
132 }
133
134 static void vproutn(char *fmt, va_list ap) 
135 {
136     if (game.options & OPTION_CURSES) {
137         vwprintw(curwnd, fmt, ap);
138         wrefresh(curwnd);
139     }
140     else
141         vprintf(fmt, ap);
142 }
143
144 void proutn(char *fmt, ...) 
145 {
146     va_list ap;
147     va_start(ap, fmt);
148     vproutn(fmt, ap);
149     va_end(ap);
150 }
151
152 void prout(char *fmt, ...) 
153 {
154     va_list ap;
155     va_start(ap, fmt);
156     vproutn(fmt, ap);
157     va_end(ap);
158     skip(1);
159 }
160
161 void prouts(char *fmt, ...) 
162 /* print slowly! */
163 {
164     char *s, buf[BUFSIZ];
165     va_list ap;
166     va_start(ap, fmt);
167     vsprintf(buf, fmt, ap);
168     va_end(ap);
169     skip(1);
170     for (s = buf; *s; s++) {
171         delay(500);
172         if (game.options & OPTION_CURSES) {
173             waddch(curwnd, *s);
174             wrefresh(curwnd);
175         }
176         else {
177             putchar(*s);
178             fflush(stdout);
179         }
180     }
181 }
182
183 void cgetline(char *line, int max)
184 {
185     if (game.options & OPTION_CURSES) {
186         wgetnstr(curwnd, line, max);
187         strcat(line, "\n");
188         wrefresh(curwnd);
189     } else {
190         fgets(line, max, stdin);
191     }
192     line[strlen(line)-1] = '\0';
193 }
194
195 void setwnd(WINDOW *wnd)
196 /* change windows -- OK for this to be a no-op in tty mode */
197 {
198     if (game.options & OPTION_CURSES) {
199      curwnd=wnd;
200      curs_set(wnd == fullscreen_window || wnd == message_window || wnd == prompt_window);
201     }
202 }
203
204 void clreol (void)
205 /* clear to end of line -- can be a no-op in tty mode */
206 {
207    if (game.options & OPTION_CURSES) {
208        wclrtoeol(curwnd);
209        wrefresh(curwnd);
210    }
211 }
212
213 void clrscr (void)
214 /* clear screen -- can be a no-op in tty mode */
215 {
216    if (game.options & OPTION_CURSES) {
217        wclear(curwnd);
218        wmove(curwnd,0,0);
219        wrefresh(curwnd);
220    }
221 }
222
223 void textcolor (int color)
224 {
225 #ifdef A_COLOR
226     if (game.options & OPTION_CURSES) {
227         switch(color) {
228         case DEFAULT: 
229             wattrset(curwnd, 0);
230             break;
231         case BLACK: 
232             wattron(curwnd, COLOR_PAIR(COLOR_BLACK));
233             break;
234         case BLUE: 
235             wattron(curwnd, COLOR_PAIR(COLOR_BLUE));
236             break;
237         case GREEN: 
238             wattron(curwnd, COLOR_PAIR(COLOR_GREEN));
239             break;
240         case CYAN: 
241             wattron(curwnd, COLOR_PAIR(COLOR_CYAN));
242             break;
243         case RED: 
244             wattron(curwnd, COLOR_PAIR(COLOR_RED));
245             break;
246         case MAGENTA: 
247             wattron(curwnd, COLOR_PAIR(COLOR_MAGENTA));
248             break;
249         case BROWN: 
250             wattron(curwnd, COLOR_PAIR(COLOR_YELLOW));
251             break;
252         case LIGHTGRAY: 
253             wattron(curwnd, COLOR_PAIR(COLOR_WHITE));
254             break;
255         case DARKGRAY: 
256             wattron(curwnd, COLOR_PAIR(COLOR_BLACK) | A_BOLD);
257             break;
258         case LIGHTBLUE: 
259             wattron(curwnd, COLOR_PAIR(COLOR_BLUE) | A_BOLD);
260             break;
261         case LIGHTGREEN: 
262             wattron(curwnd, COLOR_PAIR(COLOR_GREEN) | A_BOLD);
263             break;
264         case LIGHTCYAN: 
265             wattron(curwnd, COLOR_PAIR(COLOR_CYAN) | A_BOLD);
266             break;
267         case LIGHTRED: 
268             wattron(curwnd, COLOR_PAIR(COLOR_RED) | A_BOLD);
269             break;
270         case LIGHTMAGENTA: 
271             wattron(curwnd, COLOR_PAIR(COLOR_MAGENTA) | A_BOLD);
272             break;
273         case YELLOW: 
274             wattron(curwnd, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
275             break;
276         case WHITE:
277             wattron(curwnd, COLOR_PAIR(COLOR_WHITE) | A_BOLD);
278             break;
279         }
280     }
281 #endif /* A_COLOR */
282 }
283
284 void highvideo (void)
285 {
286     if (game.options & OPTION_CURSES) {
287         wattron(curwnd, A_REVERSE);
288     }
289 }
290  
291 void commandhook(char *cmd, int before) {
292 }
293
294 /*
295  * Things past this point have policy implications.
296  */
297
298 void drawmaps(short l)
299 /* hook to be called after moving to redraw maps */
300 {
301     if (game.options & OPTION_CURSES) {
302         if (l == 1)
303             sensor(FALSE);
304         if (l != 2) {
305             setwnd(srscan_window);
306             wmove(curwnd, 0, 0);
307             enqueue("no");
308             srscan(SCAN_FULL);
309             setwnd(report_window);
310             wclear(report_window);
311             wmove(report_window, 0, 0);
312             srscan(SCAN_NO_LEFTSIDE);
313             setwnd(lrscan_window);
314             wclear(lrscan_window);
315             wmove(lrscan_window, 0, 0);
316             enqueue("l");
317             lrscan();
318         }
319     }
320 }
321
322 void boom(int ii, int jj)
323 /* enemy fall down, go boom */ 
324 {
325     if (game.options & OPTION_CURSES) {
326         setwnd(srscan_window);
327         drawmaps(2);
328         wmove(srscan_window, ii*2+3, jj+2);
329         wattron(srscan_window, A_REVERSE);
330         waddch(srscan_window, game.quad[ii][jj]);
331         wrefresh(srscan_window);
332         sound(500);
333         delay(1000);
334         nosound();
335         wmove(srscan_window, ii*2+3, jj+2);
336         wattroff(srscan_window, A_REVERSE);
337         waddch(srscan_window, game.quad[ii][jj]);
338         wrefresh(srscan_window);
339         setwnd(message_window);
340         delay(500);
341     }
342
343
344 void warble(void)
345 /* sound and visual effects for teleportation */
346 {
347     if (game.options & OPTION_CURSES) {
348         drawmaps(1);
349         setwnd(message_window);
350         sound(50);
351         delay(1000);
352         nosound();
353     } else
354         prouts(" . . . . . ");
355 }
356
357 void tracktorpedo(int x, int y, int ix, int iy, int wait, int l, int i, int n, int iquad)
358 /* torpedo-track animation */
359 {
360     if (!game.options & OPTION_CURSES) {
361         if (l == 1) {
362             if (n != 1) {
363                 skip(1);
364                 proutn("Track for torpedo number %d-  ", i);
365             }
366             else {
367                 skip(1);
368                 proutn("Torpedo track- ");
369             }
370         } else if (l==4 || l==9) 
371             skip(1);
372         proutn("%d - %d   ", (int)x, (int)y);
373     } else {
374         if (game.damage[DSRSENS]==0 || condit==IHDOCKED) {
375             drawmaps(2);
376             delay((wait!=1)*400);
377             if ((game.quad[ix][iy]==IHDOT)||(game.quad[ix][iy]==IHBLANK)){
378                 game.quad[ix][iy]='+';
379                 drawmaps(2);
380                 game.quad[ix][iy]=iquad;
381                 sound(l*10);
382                 delay(100);
383                 nosound();
384             }
385             else {
386                 game.quad[ix][iy] |= DAMAGED;
387                 drawmaps(2);
388                 game.quad[ix][iy]=iquad;
389                 sound(500);
390                 delay(1000);
391                 nosound();
392                 wattroff(curwnd, A_REVERSE);
393             }
394         } else {
395             proutn("%d - %d   ", (int)x, (int)y);
396         }
397     }
398 }
399
400 void makechart(void) 
401 {
402     if (game.options & OPTION_CURSES) {
403         setwnd(message_window);
404         wclear(message_window);
405         chart(0);
406     }
407 }
408
409 void setpassword(void) 
410 {
411     if (!game.options & OPTION_CURSES) {
412         while (TRUE) {
413             scan();
414             strcpy(game.passwd, citem);
415             chew();
416             if (*game.passwd != 0) break;
417             proutn("Please type in a secret password-");
418         }
419     } else {
420         int i;
421         for(i=0;i<3;i++) game.passwd[i]=(char)(97+(int)(Rand()*25));
422         game.passwd[3]=0;
423     }
424 }
425