A step towards validation.
[super-star-trek.git] / io.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <termios.h>
5 #include <curses.h>
6 #include <signal.h>
7 #include <ctype.h>
8 #include <stdarg.h>
9 #include <time.h>
10
11 #include "conio.h"
12 #include "sst.h"
13
14 #ifndef SERGEEV
15 static int linecount;   /* for paging */
16 static int screenheight = 24, screenwidth = 80;
17 #endif /* SERGEEV */
18 #ifndef SERGEEV
19 static int curses = FALSE;
20 #else /* SERGEEV */
21 static int curses = TRUE;
22 #endif /* SERGEEV */
23
24 #ifdef SERGEEV
25 wnd wnds[6]={{1,1,80,25},       /* FULLSCREEN_WINDOW */
26              {1,1,25,12},       /* LEFTUPPER_WINDOW */
27              {26,2,80,12},      /* SRSCAN_WINDOW */
28              {65,1,80,10},      /* LRSCAN_WINDOW */
29              {1,13,80,23},      /* LOWER_WINDOW */
30              {1,24,80,25},      /* BOTTOM_WINDOW */
31 };
32 short curwnd;
33 #endif /* SERGEEV */
34
35 #ifndef SERGEEV
36 static void outro(int sig) {
37 /* wrap up, either normally or due to signal */
38     if (curses) {
39         clear();
40         (void)refresh();
41         (void)resetterm();
42         //(void)echo();
43         (void)endwin();
44     }
45 }
46
47 static void fastexit(int sig) {
48     outro(sig);
49     putchar('\n');
50     exit(0);
51 }
52 #endif /* SERGEEV */
53
54 void iostart(int usecurses) {
55 #ifdef SERGEEV
56         textattr(7);
57         clrscr();
58         setwnd(FULLSCREEN_WINDOW);
59 #else
60         (void) signal(SIGINT, fastexit);
61         (void) signal(SIGINT, fastexit);
62 #ifdef SIGIOT
63         (void) signal(SIGIOT,fastexit);         /* for assert(3) */
64 #endif /* SIGIOT */
65         if(signal(SIGQUIT,SIG_IGN) != SIG_IGN)
66             (void)signal(SIGQUIT,fastexit);
67
68         if ((curses = usecurses)) {
69                 (void)initscr();
70 #ifdef KEY_MIN
71                 keypad(stdscr, TRUE);
72 #endif /* KEY_MIN */
73                 (void)saveterm();
74                 (void)nonl();
75                 (void)cbreak();
76                 //(void)noecho();
77                 scrollok(stdscr, TRUE);
78                 getmaxyx(stdscr, screenheight, screenwidth);
79         } else {
80                 char *LINES = getenv("LINES");
81                 if (LINES)
82                     screenheight = atoi(LINES);
83         }
84 #endif /* SERGEEV */
85 }
86
87 void ioend(void) {
88 #ifndef SERGEEV
89     outro(0);
90 #endif /* SERGEEV */
91 }
92
93 void waitfor(void) {
94 /* wait for user action -- OK to do nothing if on a TTY */
95 #ifdef SERGEEV
96         getche();
97 #endif /* SERGEEV */
98 }
99
100 void pause_game(int i) {
101         char *prompt;
102 #ifndef SERGEEV
103         char buf[BUFSIZ];
104 #else /* SERGEEV */
105         drawmaps(0);
106         setwnd(BOTTOM_WINDOW);
107 #endif /* SERGEEV */
108         if (i==1) {
109                 if (skill > 2)
110                         prompt = "[ANOUNCEMENT ARRIVING...]";
111                 else
112                         prompt = "[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]";
113         }
114         else {
115                 if (skill > 2)
116                         prompt = "[CONTINUE?]";
117                 else
118                         prompt = "[PRESS ENTER TO CONTINUE]";
119
120         }
121 #ifndef SERGEEV
122         if (curses) {
123             waddch(stdscr, '\n');
124                 waddstr(stdscr, prompt);
125                 wgetnstr(stdscr, buf, sizeof(buf));
126                 wclear(stdscr);
127                 wrefresh(stdscr);
128         } else {
129                 putchar('\n');
130                 proutn(prompt);
131                 fgets(buf, sizeof(buf), stdin);
132                 if (i != 0) {
133                     /* much more in that old-TTY spirit to throw linefeeds */
134                     int j;
135                     for (j = 0; j < screenheight; j++)
136                         putchar('\n');
137                 }
138                 linecount = 0;
139         }
140 #else /* SERGEEV */
141         proutn(prompt);
142         getche();
143         clrscr();
144         setwnd(LOWER_WINDOW);
145         clrscr();
146 #endif /* SERGEEV */
147 }
148
149
150 void skip(int i) {
151 #ifndef SERGEEV
152     while (i-- > 0) {
153         if (curses) {
154             int y, x;
155             getyx(stdscr, y, x);
156             if (y == screenheight-1)
157                 pause_game(0);
158             else
159                 waddch(stdscr, '\n');
160         } else {
161             linecount++;
162             if (linecount >= screenheight)
163                 pause_game(0);
164             else
165                 putchar('\n');
166         }
167 #else /* SERGEEV */
168         while (i-- > 0) proutn("\n\r");
169 #endif /* SERGEEV */
170 }
171
172 static void vproutn(char *fmt, va_list ap) {
173 #ifdef SERGEEV
174     char *s, *p;
175     vasprintf(&s, fmt, ap);
176     p=s;
177     if ((curwnd==LOWER_WINDOW)&&(wherey()==wnds[curwnd].wndbottom-wnds[curwnd].wndtop)){
178        if (strchr(s,'\n')) {
179           p=strchr(s,'\n');
180           p[0]=0;
181           cprintf("%s",s);
182           p++;
183           pause_game(0);
184        }
185 #endif /* SERGEEV */
186     }
187 #ifdef SERGEEV
188     if ((curwnd==LOWER_WINDOW)&&(wherey()>wnds[curwnd].wndbottom-wnds[curwnd].wndtop+1))
189        cprintf("\r");
190 //        setwnd(curwnd);
191     if (strchr(s,'\n') || strchr(s,'\r')) clreol();
192     cprintf("%s",p);
193     free(s);
194 #endif /* SERGEEV */
195 }
196
197 void proutn(char *fmt, ...) {
198     va_list ap;
199     va_start(ap, fmt);
200 #ifndef SERGEEV
201     if (curses) {
202         vw_printw(stdscr, fmt, ap);
203         wrefresh(stdscr);
204     } else
205         vprintf(fmt, ap);
206 #else /* SERGEEV */
207     vproutn(fmt, ap);
208 #endif /* SERGEEV */
209     va_end(ap);
210 }
211
212 void prout(char *fmt, ...) {
213     va_list ap;
214     va_start(ap, fmt);
215 #ifndef SERGEEV
216     if (curses) {
217         vw_printw(stdscr, fmt, ap);
218         wrefresh(stdscr);
219     } else
220         vprintf(fmt, ap);
221 #else /* SERGEEV */
222     vproutn(fmt, ap);
223 #endif /* SERGEEV */
224     va_end(ap);
225     skip(1);
226 }
227
228 void proutc(char *line) {
229     line[strlen(line)-1] = '\0';
230 #ifndef SERGEEV
231     if (curses)
232         waddstr(stdscr, line);
233     else
234         fputs(line, stdout);
235 #else /* SERGEEV */
236     cputs(line);
237 #endif /* SERGEEV */
238     skip(1);
239 }
240
241 #ifdef SERGEEV
242 static void prchr(char *s){
243      char str[2];
244      strncpy(str,s,1);
245      str[1]=0;
246      proutn(str);
247 }
248
249 static void vprouts(char *fmt, va_list ap) {
250     char *s, *p;
251     vasprintf(&s, fmt, ap);
252     p=s;
253     while (*p) {
254         prchr(p++);
255         delay(30);
256     }
257     free(s);
258 }
259 #endif /* SERGEEV */
260
261 void prouts(char *fmt, ...) {
262 #ifndef SERGEEV
263         clock_t endTime;
264         char *s, buf[BUFSIZ];
265         /* print slowly! */
266         va_list ap;
267         va_start(ap, fmt);
268         vsprintf(buf, fmt, ap);
269         va_end(ap);
270         skip(1);
271         for (s = buf; *s; s++) {
272                 endTime = clock() + CLOCKS_PER_SEC*0.05;
273                 while (clock() < endTime) continue;
274                 if (curses) {
275                     waddch(stdscr, *s);
276                     wrefresh(stdscr);
277                 }
278                 else {
279                     putchar(*s);
280                     fflush(stdout);
281                 }
282         }
283 #else /* SERGEEV */
284     va_list ap;
285     va_start(ap, fmt);
286     vprouts(fmt, ap);
287     va_end(ap);
288 #endif /* SERGEEV */
289 }
290
291 void c_printf (char *format, ... )
292 {
293     char buffer[BUFSIZ]; /* Well, BUFSIZ is from ncurses...  */
294     va_list argp;
295     va_start(argp,format);
296     vsprintf(buffer,format,argp);
297     va_end(argp);
298 #ifdef SERGEEV
299     waddstr(conio_scr,buffer);
300 #else
301     proutn(buffer);
302 #endif /* SERGEEV */
303 }
304
305 void cgetline(char *line, int max) {
306     if (curses) {
307 #ifndef SERGEEV
308         wgetnstr(stdscr, line, max);
309         wrefresh(stdscr);
310 #else /* SERGEEV */
311         line[0]=max-1;
312         cgets(line);
313         memmove(line,&line[2],max-3);
314 #endif /* SERGEEV */
315     } else {
316         fgets(line, max, stdin);
317         line[strlen(line)-1] = '\0';
318     }
319 }
320
321 void setwnd(short wndnum){
322 /* change windows -- OK for this to be a no-op in tty mode */
323 #ifdef SERGEEV
324      int cury;
325      cury=wherey()+wnds[curwnd].wndtop-wnds[wndnum].wndtop;
326      if ((curwnd==FULLSCREEN_WINDOW)&&(wndnum!=FULLSCREEN_WINDOW)) clrscr();
327      window(wnds[wndnum].wndleft, wnds[wndnum].wndtop, wnds[wndnum].wndright, wnds[wndnum].wndbottom);
328      if ((curwnd==wndnum)&&(cury>wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1)){
329         gotoxy(wnds[wndnum].wndright-wnds[wndnum].wndleft+1,wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1);
330         skip(1);
331      }
332      curwnd=wndnum;
333      gotoxy(1,cury);
334 #endif /* SERGEEV */
335 }
336
337 void commandhook(char *cmd, int before) {
338 }
339
340 /*
341  * Things past this point have policy implications.
342  */
343
344 void drawmaps(short l) {
345 /* hook to be called after moving to redraw maps */
346 #ifdef SERGEEV
347      _setcursortype(_NOCURSOR);
348      if (l==1) sensor();
349      if (l!=2) setwnd(LEFTUPPER_WINDOW);
350      gotoxy(1,1);
351      enqueue("s");
352      srscan(SCAN_FULL);
353      if (l!=2){
354         setwnd(SRSCAN_WINDOW);
355         clrscr();
356         srscan(SCAN_NO_LEFTSIDE);
357         setwnd(LRSCAN_WINDOW);
358         clrscr();
359         enqueue("l");
360         lrscan();
361         _setcursortype(_NORMALCURSOR);
362      }
363 #endif /* SERGEEV */
364 }
365
366 void boom(int ii, int jj)
367 /* enemy fall down, go boom */ 
368 {
369 #ifdef SERGEEV
370     int crx, cry;
371     crx=wherex();
372     cry=wherey();
373     setwnd(LEFTUPPER_WINDOW);
374     drawmaps(2);
375     gotoxy(jj*2+3,ii+2);
376     highvideo();
377     proutn("%c", game.quad[ii][jj]);
378     gotoxy(wherex()-1,wherey());
379     sound(500);
380     delay(1000);
381     nosound();
382     lowvideo();
383     proutn("%c", game.quad[ii][jj]);
384     setwnd(LOWER_WINDOW);
385     gotoxy(crx,cry);
386     _setcursortype(_NORMALCURSOR);
387     delay(500);
388 #endif /* SERGEEV */
389
390
391 void warble(void)
392 /* sound and visual effects for teleportation */
393 {
394 #ifdef SERGEEV
395     int posx, posy;
396     posx=wherex();
397     posy=wherey();
398     drawmaps(1);
399     setwnd(LOWER_WINDOW);
400     gotoxy(posx,posy);
401     sound(50);
402     delay(1000);
403     nosound();
404 #else
405     prouts(" . . . . . ");
406 #endif /* SERGEEV */
407 }
408
409 void tracktorpedo(int x, int y, int ix, int iy, int wait, int l, int i, int n, int iquad)
410 /* torpedo-track animation */
411 {
412 #ifndef SERGEEV
413     if (l == 1) {
414         if (n != 1) {
415             skip(1);
416             proutn("Track for torpedo number %d-  ", i);
417         }
418         else {
419             skip(1);
420             proutn("Torpedo track- ");
421         }
422     } else if (l==4 || l==9) 
423         skip(1);
424     proutn("%d - %d   ", (int)x, (int)y);
425 #else
426     if (game.damage[DSRSENS]==0 || condit==IHDOCKED) {
427         drawmaps(2);
428         delay((wait!=1)*400);
429         gotoxy(iy*2+3,ix+2);
430         if ((game.quad[ix][iy]==IHDOT)||(game.quad[ix][iy]==IHBLANK)){
431             game.quad[ix][iy]='+';
432             drawmaps(2);
433             game.quad[ix][iy]=iquad;
434             sound(l*10);
435             delay(100);
436             nosound();
437         }
438         else {
439             game.quad[ix][iy]|=128;
440             drawmaps(2);
441             game.quad[ix][iy]=iquad;
442             _setcursortype(_NOCURSOR);
443             sound(500);
444             delay(1000);
445             nosound();
446             lowvideo();
447             _setcursortype(_NORMALCURSOR);
448         }
449     } else {
450         proutn("%d - %d   ", (int)x, (int)y);
451     }
452 #endif /* SERGEEV */
453 }
454
455 void makechart(void) {
456 #ifdef SERGEEV
457     _setcursortype(_NOCURSOR);
458     setwnd(LOWER_WINDOW);
459     clrscr();
460     chart(0);
461     _setcursortype(_NORMALCURSOR);
462 #endif /* SERGEEV */
463 }
464
465 void setpassword(void) {
466 #ifndef SERGEEV
467         while (TRUE) {
468                 scan();
469                 strcpy(game.passwd, citem);
470                 chew();
471                 if (*game.passwd != 0) break;
472                 proutn("Please type in a secret password-");
473         }
474 #else
475         int i;
476         for(i=0;i<3;i++) game.passwd[i]=(char)(97+(int)(Rand()*25));
477         game.passwd[3]=0;
478 #endif /* SERGEEV */
479 }
480