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