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