1 1.2 kamil /* Header: term.c,v 7.0.1.2 86/12/12 17:04:09 lwall Exp */ 2 1.1 kamil 3 1.2 kamil /* Log: term.c,v 4 1.1 kamil * Revision 7.0.1.2 86/12/12 17:04:09 lwall 5 1.1 kamil * Baseline for net release. 6 1.8 rillig * 7 1.1 kamil * Revision 7.0.1.1 86/10/16 10:53:20 lwall 8 1.1 kamil * Added Damage. Fixed random bugs. 9 1.8 rillig * 10 1.1 kamil * Revision 7.0 86/10/08 15:14:02 lwall 11 1.1 kamil * Split into separate files. Added amoebas and pirates. 12 1.8 rillig * 13 1.1 kamil */ 14 1.1 kamil 15 1.1 kamil #include "EXTERN.h" 16 1.1 kamil #include "warp.h" 17 1.1 kamil #include "bang.h" 18 1.1 kamil #include "intrp.h" 19 1.1 kamil #include "object.h" 20 1.1 kamil #include "play.h" 21 1.1 kamil #include "score.h" 22 1.1 kamil #include "sig.h" 23 1.1 kamil #include "us.h" 24 1.1 kamil #include "util.h" 25 1.1 kamil #include "weapon.h" 26 1.1 kamil #include "INTERN.h" 27 1.1 kamil #include "term.h" 28 1.1 kamil 29 1.4 christos int typeahead = false; 30 1.1 kamil 31 1.1 kamil char tcarea[TCSIZE]; /* area for "compiled" termcap strings */ 32 1.1 kamil 33 1.4 christos /* guarantee capability pointer != NULL */ 34 1.1 kamil /* (I believe terminfo will ignore the &tmpaddr argument.) */ 35 1.1 kamil 36 1.1 kamil #define Tgetstr(key) ((tstr = tgetstr(key,&tmpaddr)) ? tstr : nullstr) 37 1.1 kamil 38 1.1 kamil #ifdef PUSHBACK 39 1.1 kamil struct keymap { 40 1.1 kamil char km_type[128]; 41 1.1 kamil union km_union { 42 1.1 kamil struct keymap *km_km; 43 1.1 kamil char *km_str; 44 1.1 kamil } km_ptr[128]; 45 1.1 kamil }; 46 1.1 kamil 47 1.1 kamil #define KM_NOTHIN 0 48 1.1 kamil #define KM_STRING 1 49 1.1 kamil #define KM_KEYMAP 2 50 1.1 kamil #define KM_BOGUS 3 51 1.1 kamil 52 1.1 kamil #define KM_TMASK 3 53 1.1 kamil #define KM_GSHIFT 4 54 1.1 kamil #define KM_GMASK 7 55 1.1 kamil 56 1.1 kamil typedef struct keymap KEYMAP; 57 1.1 kamil 58 1.4 christos KEYMAP *topmap INIT(NULL); 59 1.1 kamil 60 1.4 christos void mac_init(char *); 61 1.4 christos static KEYMAP *newkeymap(void); 62 1.4 christos void pushstring(char *); 63 1.1 kamil #endif 64 1.1 kamil 65 1.1 kamil /* terminal initialization */ 66 1.1 kamil 67 1.1 kamil void 68 1.4 christos term_init(void) 69 1.1 kamil { 70 1.1 kamil savetty(); /* remember current tty state */ 71 1.1 kamil 72 1.6 christos #if defined(TERMIO) || defined(TERMIOS) 73 1.6 christos ospeed = cfgetospeed(&_tty); 74 1.1 kamil ERASECH = _tty.c_cc[VERASE]; /* for finish_command() */ 75 1.1 kamil KILLCH = _tty.c_cc[VKILL]; /* for finish_command() */ 76 1.1 kamil #else 77 1.1 kamil ospeed = _tty.sg_ospeed; /* for tputs() */ 78 1.1 kamil ERASECH = _tty.sg_erase; /* for finish_command() */ 79 1.1 kamil KILLCH = _tty.sg_kill; /* for finish_command() */ 80 1.1 kamil #endif 81 1.1 kamil 82 1.1 kamil /* The following could be a table but I can't be sure that there isn't */ 83 1.1 kamil /* some degree of sparsity out there in the world. */ 84 1.1 kamil 85 1.1 kamil switch (ospeed) { /* 1 second of padding */ 86 1.1 kamil #ifdef BEXTA 87 1.1 kamil case BEXTA: just_a_sec = 1920; break; 88 1.1 kamil #else 89 1.1 kamil #ifdef B19200 90 1.1 kamil case B19200: just_a_sec = 1920; break; 91 1.1 kamil #endif 92 1.1 kamil #endif 93 1.1 kamil case B9600: just_a_sec = 960; break; 94 1.1 kamil case B4800: just_a_sec = 480; break; 95 1.1 kamil case B2400: just_a_sec = 240; break; 96 1.1 kamil case B1800: just_a_sec = 180; break; 97 1.1 kamil case B1200: just_a_sec = 120; break; 98 1.1 kamil case B600: just_a_sec = 60; break; 99 1.1 kamil case B300: just_a_sec = 30; break; 100 1.1 kamil /* do I really have to type the rest of this??? */ 101 1.1 kamil case B200: just_a_sec = 20; break; 102 1.1 kamil case B150: just_a_sec = 15; break; 103 1.1 kamil case B134: just_a_sec = 13; break; 104 1.1 kamil case B110: just_a_sec = 11; break; 105 1.1 kamil case B75: just_a_sec = 8; break; 106 1.1 kamil case B50: just_a_sec = 5; break; 107 1.1 kamil default: just_a_sec = 960; break; 108 1.1 kamil /* if we are running detached I */ 109 1.1 kamil } /* don't want to know about it! */ 110 1.1 kamil } 111 1.1 kamil 112 1.1 kamil /* set terminal characteristics */ 113 1.1 kamil 114 1.1 kamil void 115 1.4 christos term_set(char *tcbuf) /* temp area for "uncompiled" termcap entry */ 116 1.1 kamil { 117 1.1 kamil char *tmpaddr; /* must not be register */ 118 1.4 christos char *tstr; 119 1.1 kamil char *s; 120 1.1 kamil int retval; 121 1.1 kamil 122 1.1 kamil #ifdef PENDING 123 1.1 kamil #ifndef FIONREAD 124 1.1 kamil #ifndef RDCHK 125 1.1 kamil /* do no delay reads on something that always gets closed on exit */ 126 1.1 kamil 127 1.1 kamil devtty = open("/dev/tty",0); 128 1.1 kamil if (devtty < 0) { 129 1.1 kamil printf(cantopen,"/dev/tty"); 130 1.1 kamil finalize(1); 131 1.1 kamil } 132 1.1 kamil fcntl(devtty,F_SETFL,O_NDELAY); 133 1.1 kamil #endif 134 1.1 kamil #endif 135 1.1 kamil #endif 136 1.8 rillig 137 1.1 kamil /* get all that good termcap stuff */ 138 1.1 kamil 139 1.1 kamil retval = tgetent(tcbuf,getenv("TERM")); /* get termcap entry */ 140 1.1 kamil if (retval < 1) { 141 1.1 kamil #ifdef VERBOSE 142 1.1 kamil printf("No termcap %s found.\n", retval ? "file" : "entry"); 143 1.1 kamil #else 144 1.1 kamil fputs("Termcap botch\n",stdout); 145 1.1 kamil #endif 146 1.1 kamil finalize(1); 147 1.1 kamil } 148 1.1 kamil tmpaddr = tcarea; /* set up strange tgetstr pointer */ 149 1.1 kamil s = Tgetstr("pc"); /* get pad character */ 150 1.1 kamil PC = *s; /* get it where tputs wants it */ 151 1.1 kamil if (!tgetflag("bs")) { /* is backspace not used? */ 152 1.1 kamil BC = Tgetstr("bc"); /* find out what is */ 153 1.1 kamil if (BC == nullstr) /* terminfo grok's 'bs' but not 'bc' */ 154 1.1 kamil BC = Tgetstr("le"); 155 1.1 kamil } else 156 1.4 christos BC = __UNCONST("\b"); /* make a backspace handy */ 157 1.1 kamil UP = Tgetstr("up"); /* move up a line */ 158 1.1 kamil ND = Tgetstr("nd"); /* non-destructive move cursor right */ 159 1.1 kamil DO = Tgetstr("do"); /* move cursor down */ 160 1.1 kamil if (!*DO) 161 1.1 kamil DO = Tgetstr("nl"); 162 1.1 kamil CL = Tgetstr("cl"); /* get clear string */ 163 1.1 kamil CE = Tgetstr("ce"); /* clear to end of line string */ 164 1.1 kamil CM = Tgetstr("cm"); /* cursor motion - PWP */ 165 1.1 kamil HO = Tgetstr("ho"); /* home cursor if no CM - PWP */ 166 1.1 kamil CD = Tgetstr("cd"); /* clear to end of display - PWP */ 167 1.1 kamil SO = Tgetstr("so"); /* begin standout */ 168 1.1 kamil SE = Tgetstr("se"); /* end standout */ 169 1.1 kamil if ((SG = tgetnum("sg"))<0) 170 1.1 kamil SG = 0; /* blanks left by SG, SE */ 171 1.1 kamil US = Tgetstr("us"); /* start underline */ 172 1.1 kamil UE = Tgetstr("ue"); /* end underline */ 173 1.1 kamil if ((UG = tgetnum("ug"))<0) 174 1.1 kamil UG = 0; /* blanks left by US, UE */ 175 1.1 kamil if (*US) 176 1.1 kamil UC = nullstr; /* UC must not be NULL */ 177 1.1 kamil else 178 1.1 kamil UC = Tgetstr("uc"); /* underline a character */ 179 1.1 kamil if (!*US && !*UC) { /* no underline mode? */ 180 1.1 kamil US = SO; /* substitute standout mode */ 181 1.1 kamil UE = SE; 182 1.1 kamil UG = SG; 183 1.1 kamil } 184 1.1 kamil LINES = tgetnum("li"); /* lines per page */ 185 1.1 kamil COLS = tgetnum("co"); /* columns on page */ 186 1.1 kamil AM = tgetflag("am"); /* terminal wraps automatically? */ 187 1.1 kamil XN = tgetflag("xn"); /* then eats next newline? */ 188 1.1 kamil VB = Tgetstr("vb"); 189 1.1 kamil if (!*VB) 190 1.4 christos VB = __UNCONST("\007"); 191 1.1 kamil CR = Tgetstr("cr"); 192 1.1 kamil if (!*CR) { 193 1.1 kamil if (tgetflag("nc") && *UP) { 194 1.4 christos size_t l = strlen(UP) + 2; 195 1.4 christos CR = safemalloc(l); 196 1.4 christos snprintf(CR, l, "%s\r",UP); 197 1.1 kamil } 198 1.1 kamil else 199 1.4 christos CR = __UNCONST("\r"); 200 1.1 kamil } 201 1.1 kamil if (LINES <= 0) 202 1.1 kamil LINES = 24; 203 1.1 kamil if (COLS <= 0) 204 1.1 kamil COLS = 80; 205 1.1 kamil 206 1.1 kamil BCsize = comp_tc(bsptr,BC,1); 207 1.1 kamil BC = bsptr; 208 1.1 kamil 209 1.1 kamil if (!*ND) /* not defined? */ 210 1.1 kamil NDsize = 1000; /* force cursor addressing */ 211 1.1 kamil else { 212 1.1 kamil NDsize = comp_tc(cmbuffer,ND,1); 213 1.1 kamil myND = malloc((unsigned)NDsize); 214 1.1 kamil movc3(NDsize,cmbuffer,myND); 215 1.1 kamil if (debugging) { 216 1.1 kamil int scr; 217 1.1 kamil 218 1.1 kamil printf("ND"); 219 1.1 kamil for (scr=0; scr<NDsize; scr++) 220 1.1 kamil printf(" %d",myND[scr]); 221 1.1 kamil printf("\n"); 222 1.1 kamil } 223 1.1 kamil } 224 1.1 kamil 225 1.1 kamil if (!*UP) /* not defined? */ 226 1.1 kamil UPsize = 1000; /* force cursor addressing */ 227 1.1 kamil else { 228 1.1 kamil UPsize = comp_tc(cmbuffer,UP,1); 229 1.1 kamil myUP = malloc((unsigned)UPsize); 230 1.1 kamil movc3(UPsize,cmbuffer,myUP); 231 1.1 kamil if (debugging) { 232 1.1 kamil int scr; 233 1.1 kamil 234 1.1 kamil printf("UP"); 235 1.1 kamil for (scr=0; scr<UPsize; scr++) 236 1.1 kamil printf(" %d",myUP[scr]); 237 1.1 kamil printf("\n"); 238 1.1 kamil } 239 1.1 kamil } 240 1.1 kamil 241 1.1 kamil if (!*DO) { /* not defined? */ 242 1.4 christos myDO = DO = __UNCONST("\n"); /* assume a newline */ 243 1.1 kamil DOsize = 1; 244 1.1 kamil } 245 1.1 kamil else { 246 1.1 kamil DOsize = comp_tc(cmbuffer,DO,1); 247 1.1 kamil myDO = malloc((unsigned)DOsize); 248 1.1 kamil movc3(DOsize,cmbuffer,myDO); 249 1.1 kamil if (debugging) { 250 1.1 kamil int scr; 251 1.1 kamil 252 1.1 kamil printf("DO"); 253 1.1 kamil for (scr=0; scr<DOsize; scr++) 254 1.1 kamil printf(" %d",myDO[scr]); 255 1.1 kamil printf("\n"); 256 1.1 kamil } 257 1.1 kamil } 258 1.1 kamil if (debugging) 259 1.4 christos fgets(cmbuffer,(sizeof cmbuffer),stdin); 260 1.1 kamil 261 1.1 kamil CMsize = comp_tc(cmbuffer,tgoto(CM,20,20),0); 262 1.1 kamil if (PC != '\0') { 263 1.1 kamil char *p; 264 1.1 kamil 265 1.1 kamil for (p=filler+(sizeof filler)-1;!*p;--p) 266 1.1 kamil *p = PC; 267 1.1 kamil } 268 1.6 christos charsperhalfsec = (speed_t)ospeed >= B9600 ? (speed_t)480 : 269 1.6 christos (speed_t)ospeed == B4800 ? (speed_t)240 : 270 1.6 christos (speed_t)ospeed == B2400 ? (speed_t)120 : 271 1.6 christos (speed_t)ospeed == B1200 ? (speed_t)60 : 272 1.6 christos (speed_t)ospeed == B600 ? (speed_t)30 : 273 1.6 christos /* speed is 300 (?) */ (speed_t)15; 274 1.6 christos 275 1.6 christos gfillen = (speed_t)ospeed >= B9600 ? (speed_t)(sizeof filler) : 276 1.6 christos (speed_t)ospeed == B4800 ? (speed_t)13 : 277 1.6 christos (speed_t)ospeed == B2400 ? (speed_t)7 : 278 1.6 christos (speed_t)ospeed == B1200 ? (speed_t)4 : 279 1.6 christos (speed_t)(1+BCsize); 280 1.6 christos if ((speed_t)ospeed < B2400) 281 1.4 christos lowspeed = true; 282 1.1 kamil 283 1.1 kamil strcpy(term,ttyname(2)); 284 1.1 kamil 285 1.1 kamil if (!*CM || !BCsize) 286 1.1 kamil no_can_do("dumb"); 287 1.1 kamil if (!scorespec && (LINES < 24 || COLS < 80)) 288 1.1 kamil no_can_do("puny"); 289 1.7 christos // if (LINES > 25) 290 1.7 christos // no_can_do("humongous"); 291 1.1 kamil 292 1.1 kamil crmode(); 293 1.1 kamil raw(); 294 1.1 kamil noecho(); /* turn off echo */ 295 1.1 kamil nonl(); 296 1.1 kamil 297 1.1 kamil #ifdef PUSHBACK 298 1.1 kamil mac_init(tcbuf); 299 1.1 kamil #endif 300 1.1 kamil } 301 1.1 kamil 302 1.1 kamil #ifdef PUSHBACK 303 1.1 kamil void 304 1.4 christos mac_init(char *tcbuf) 305 1.1 kamil { 306 1.1 kamil char tmpbuf[1024]; 307 1.1 kamil 308 1.1 kamil tmpfp = fopen(filexp(getval("WARPMACRO",WARPMACRO)),"r"); 309 1.4 christos if (tmpfp != NULL) { 310 1.4 christos while (fgets(tcbuf,1024,tmpfp) != NULL) { 311 1.1 kamil mac_line(tcbuf,tmpbuf,(sizeof tmpbuf)); 312 1.1 kamil } 313 1.4 christos fclose(tmpfp); 314 1.1 kamil } 315 1.1 kamil } 316 1.1 kamil 317 1.1 kamil void 318 1.4 christos mac_line(char *line, char *tmpbuf, size_t tbsize) 319 1.1 kamil { 320 1.4 christos char *s; 321 1.4 christos char *m; 322 1.4 christos KEYMAP *curmap; 323 1.4 christos int ch; 324 1.4 christos int garbage = 0; 325 1.4 christos static const char override[] = "\r\nkeymap overrides string\r\n"; 326 1.1 kamil 327 1.4 christos if (topmap == NULL) 328 1.1 kamil topmap = newkeymap(); 329 1.1 kamil if (*line == '#' || *line == '\n') 330 1.1 kamil return; 331 1.1 kamil if (line[ch = strlen(line)-1] == '\n') 332 1.1 kamil line[ch] = '\0'; 333 1.1 kamil m = dointerp(tmpbuf,tbsize,line," \t"); 334 1.1 kamil if (!*m) 335 1.1 kamil return; 336 1.1 kamil while (*m == ' ' || *m == '\t') m++; 337 1.1 kamil for (s=tmpbuf,curmap=topmap; *s; s++) { 338 1.1 kamil ch = *s & 0177; 339 1.4 christos if (s[1] == '+' && isdigit((unsigned char)s[2])) { 340 1.1 kamil s += 2; 341 1.1 kamil garbage = (*s & KM_GMASK) << KM_GSHIFT; 342 1.1 kamil } 343 1.1 kamil else 344 1.1 kamil garbage = 0; 345 1.1 kamil if (s[1]) { 346 1.1 kamil if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) { 347 1.1 kamil puts(override); 348 1.1 kamil free(curmap->km_ptr[ch].km_str); 349 1.4 christos curmap->km_ptr[ch].km_str = NULL; 350 1.1 kamil } 351 1.1 kamil curmap->km_type[ch] = KM_KEYMAP + garbage; 352 1.4 christos if (curmap->km_ptr[ch].km_km == NULL) 353 1.1 kamil curmap->km_ptr[ch].km_km = newkeymap(); 354 1.1 kamil curmap = curmap->km_ptr[ch].km_km; 355 1.1 kamil } 356 1.1 kamil else { 357 1.1 kamil if ((curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP) 358 1.1 kamil puts(override); 359 1.1 kamil else { 360 1.1 kamil curmap->km_type[ch] = KM_STRING + garbage; 361 1.1 kamil curmap->km_ptr[ch].km_str = savestr(m); 362 1.1 kamil } 363 1.1 kamil } 364 1.1 kamil } 365 1.1 kamil } 366 1.1 kamil 367 1.4 christos static KEYMAP* 368 1.4 christos newkeymap(void) 369 1.1 kamil { 370 1.4 christos int i; 371 1.4 christos KEYMAP *map; 372 1.1 kamil 373 1.1 kamil #ifndef lint 374 1.1 kamil map = (KEYMAP*)safemalloc(sizeof(KEYMAP)); 375 1.1 kamil #else 376 1.1 kamil map = Null(KEYMAP*); 377 1.1 kamil #endif /* lint */ 378 1.1 kamil for (i=127; i>=0; --i) { 379 1.4 christos map->km_ptr[i].km_km = NULL; 380 1.1 kamil map->km_type[i] = KM_NOTHIN; 381 1.1 kamil } 382 1.1 kamil return map; 383 1.1 kamil } 384 1.1 kamil 385 1.1 kamil #endif 386 1.1 kamil 387 1.1 kamil /* print out a file, stopping at form feeds */ 388 1.1 kamil 389 1.1 kamil void 390 1.4 christos page(const char *filename, size_t num) 391 1.1 kamil { 392 1.1 kamil int linenum = 1; 393 1.1 kamil 394 1.1 kamil tmpfp = fopen(filename,"r"); 395 1.1 kamil if (tmpfp != NULL) { 396 1.1 kamil while (fgets(spbuf,(sizeof spbuf),tmpfp) != NULL) { 397 1.1 kamil if (*spbuf == '\f') { 398 1.1 kamil printf("[Type anything to continue] "); 399 1.4 christos fflush(stdout); 400 1.1 kamil getcmd(spbuf); 401 1.1 kamil printf("\r\n"); 402 1.1 kamil if (*spbuf == INTRCH) 403 1.1 kamil finalize(0); 404 1.1 kamil if (*spbuf == 'q' || *spbuf == 'Q') 405 1.1 kamil break; 406 1.1 kamil } 407 1.1 kamil else { 408 1.1 kamil if (num) 409 1.1 kamil printf("%3d %s\r",linenum++,spbuf); 410 1.1 kamil else 411 1.1 kamil printf("%s\r",spbuf); 412 1.1 kamil } 413 1.1 kamil } 414 1.4 christos fclose(tmpfp); 415 1.1 kamil } 416 1.1 kamil } 417 1.1 kamil 418 1.1 kamil void 419 1.4 christos move(int y, int x, int chadd) 420 1.1 kamil { 421 1.4 christos int ydist; 422 1.4 christos int xdist; 423 1.4 christos int i; 424 1.4 christos char *s; 425 1.1 kamil 426 1.1 kamil ydist = y - real_y; 427 1.1 kamil xdist = x - real_x; 428 1.1 kamil i = ydist * (ydist < 0 ? -UPsize : DOsize) + 429 1.1 kamil xdist * (xdist < 0 ? -BCsize : NDsize); 430 1.1 kamil beg_qwrite(); 431 1.1 kamil if (i <= CMsize) { 432 1.1 kamil if (ydist < 0) 433 1.1 kamil for (; ydist; ydist++) 434 1.1 kamil for (i=UPsize,s=myUP; i; i--) 435 1.1 kamil qaddch(*s++); 436 1.1 kamil else 437 1.1 kamil for (; ydist; ydist--) 438 1.1 kamil for (i=DOsize,s=myDO; i; i--) 439 1.1 kamil qaddch(*s++); 440 1.1 kamil if (xdist < 0) 441 1.1 kamil for (; xdist; xdist++) 442 1.1 kamil for (i=BCsize,s=BC; i; i--) 443 1.1 kamil qaddch(*s++); 444 1.1 kamil else 445 1.1 kamil for (; xdist; xdist--) 446 1.1 kamil for (i=NDsize,s=myND; i; i--) 447 1.1 kamil qaddch(*s++); 448 1.1 kamil } 449 1.1 kamil else { 450 1.1 kamil tputs(tgoto(CM,x,y),0,cmstore); 451 1.1 kamil } 452 1.1 kamil real_y = y; 453 1.1 kamil real_x = x; 454 1.1 kamil if (chadd) { 455 1.1 kamil qaddch(chadd); 456 1.1 kamil } 457 1.1 kamil if (maxcmstring != cmbuffer) 458 1.1 kamil end_qwrite(); 459 1.1 kamil } 460 1.1 kamil 461 1.1 kamil void 462 1.4 christos do_tc(const char *s, int l) 463 1.1 kamil { 464 1.1 kamil beg_qwrite(); 465 1.1 kamil tputs(s,l,cmstore); 466 1.1 kamil end_qwrite(); 467 1.1 kamil } 468 1.1 kamil 469 1.1 kamil int 470 1.4 christos comp_tc(char *dest, const char *s, int l) 471 1.1 kamil { 472 1.1 kamil maxcmstring = dest; 473 1.1 kamil tputs(s,l,cmstore); 474 1.1 kamil return(maxcmstring-dest); 475 1.1 kamil } 476 1.1 kamil 477 1.1 kamil void 478 1.4 christos helper(void) 479 1.1 kamil { 480 1.1 kamil clear(); 481 1.1 kamil mvaddstr(0,4,"h or 4 left"); 482 1.1 kamil mvaddstr(1,4,"j or 2 down Use with SHIFT to fire torpedoes."); 483 1.1 kamil mvaddstr(2,4,"k or 8 up Use with CTRL or FUNCT to fire"); 484 1.1 kamil mvaddstr(3,4,"l or 6 right phasers or turbolasers."); 485 1.1 kamil mvaddstr(4,4,"b or 1 down and left Use preceded by 'a' or 'r' for"); 486 1.1 kamil mvaddstr(5,4,"n or 3 down and right attractors or repulsors."); 487 1.1 kamil mvaddstr(6,4,"y or 7 up and left Use normally for E or B motion."); 488 1.1 kamil mvaddstr(7,4,"u or 9 up and right"); 489 1.1 kamil mvaddstr(8,4,""); 490 1.1 kamil mvaddstr(9,4,"del or % fire photon torpedoes in every (reasonable) direction."); 491 1.1 kamil mvaddstr(10,4,"s stop all torpedoes."); 492 1.1 kamil mvaddstr(11,4,"S or 0 stop the Enterprise when in warp mode."); 493 1.1 kamil mvaddstr(12,4,"d/D destruct all torpedoes/current vessel."); 494 1.1 kamil mvaddstr(13,4,"i/w switch to Enterprise & put into impulse/warp mode."); 495 1.1 kamil mvaddstr(14,4,"c/v switch to Enterprise & make cloaked/visible."); 496 1.1 kamil mvaddstr(15,4,"p switch to Base."); 497 1.1 kamil mvaddstr(16,4,"o toggle to other vessel (from E to B, or vice versa.)"); 498 1.1 kamil mvaddstr(17,4,"z zap (suppress) blasts near Enterprise next cycle"); 499 1.1 kamil mvaddstr(18,4,""); 500 1.1 kamil mvaddstr(19,4,"^R refresh the screen. ^Z suspend the game."); 501 1.1 kamil mvaddstr(20,4,"q exit this round (if you haven't typed q within 10 cycles)."); 502 1.1 kamil mvaddstr(21,4,"Q exit this game."); 503 1.1 kamil mvaddstr(22,4,""); 504 1.1 kamil mvaddstr(23,4," [Hit space to continue]"); 505 1.4 christos fflush(stdout); 506 1.1 kamil do { 507 1.1 kamil getcmd(spbuf); 508 1.1 kamil } while (*spbuf != ' '); 509 1.1 kamil rewrite(); 510 1.8 rillig 511 1.1 kamil } 512 1.1 kamil 513 1.1 kamil void 514 1.4 christos rewrite(void) 515 1.1 kamil { 516 1.4 christos int x; 517 1.4 christos int y; 518 1.4 christos OBJECT *obj; 519 1.1 kamil 520 1.1 kamil clear(); 521 1.1 kamil for (y=0; y<YSIZE; y++) { 522 1.1 kamil for (x=0; x<XSIZE; x++) { 523 1.1 kamil if (numamoebas && amb[y][x] != ' ') 524 1.1 kamil mvaddc(y+1,x*2,amb[y][x]); 525 1.4 christos if ((obj = occupant[y][x]) != NULL) { 526 1.1 kamil if (obj->image != ' ') 527 1.1 kamil mvaddc(y+1,x*2,obj->image); 528 1.1 kamil } 529 1.1 kamil } 530 1.1 kamil } 531 1.4 christos snprintf(spbuf, sizeof(spbuf), 532 1.4 christos "%-4s E: %4d %2d B: %5d %3d Enemies: %-3d Stars: %-3d Stardate%5d.%1d %9ld", 533 1.1 kamil " ", 0, 0, 0, 0, 0, 0, timer/10+smarts*100, timer%10, 0L); 534 1.1 kamil mvaddstr(0,0,spbuf); 535 1.1 kamil oldeenergy = oldbenergy = oldcurscore = 536 1.1 kamil oldstatus = oldetorp = oldbtorp = oldstrs = oldenemies = -1; 537 1.1 kamil /* force everything to fill in */ 538 1.1 kamil if (damage) 539 1.1 kamil olddamage = 0; 540 1.1 kamil if (!ent) 541 1.1 kamil etorp = 0; 542 1.1 kamil if (!base) 543 1.1 kamil btorp = 0; 544 1.1 kamil display_status(); 545 1.1 kamil } 546 1.1 kamil 547 1.3 kamil int 548 1.4 christos cmstore(int ch) 549 1.1 kamil { 550 1.1 kamil *maxcmstring++ = ch; 551 1.4 christos return 0; 552 1.1 kamil } 553 1.1 kamil 554 1.1 kamil /* discard any characters typed ahead */ 555 1.1 kamil 556 1.1 kamil void 557 1.4 christos eat_typeahead(void) 558 1.1 kamil { 559 1.1 kamil #ifdef PUSHBACK 560 1.1 kamil if (!typeahead && nextin==nextout) /* cancel only keyboard stuff */ 561 1.1 kamil #else 562 1.1 kamil if (!typeahead) 563 1.1 kamil #endif 564 1.1 kamil { 565 1.1 kamil #ifdef PENDING 566 1.1 kamil while (input_pending()) 567 1.4 christos read_tty(buf,sizeof(buf)); 568 1.1 kamil #else /* this is probably v7, with no rdchk() */ 569 1.1 kamil ioctl(_tty_ch,TIOCSETP,&_tty); 570 1.1 kamil #endif 571 1.1 kamil } 572 1.1 kamil } 573 1.1 kamil 574 1.1 kamil void 575 1.4 christos settle_down(void) 576 1.1 kamil { 577 1.1 kamil dingaling(); 578 1.4 christos fflush(stdout); 579 1.1 kamil sleep(1); 580 1.1 kamil #ifdef PUSHBACK 581 1.1 kamil nextout = nextin; /* empty circlebuf */ 582 1.1 kamil #endif 583 1.1 kamil eat_typeahead(); 584 1.1 kamil } 585 1.1 kamil 586 1.1 kamil #ifdef PUSHBACK 587 1.1 kamil /* read a character from the terminal, with multi-character pushback */ 588 1.1 kamil 589 1.1 kamil int 590 1.4 christos read_tty(char *addr, ssize_t size) /* ignored for now */ 591 1.1 kamil { 592 1.1 kamil if (nextout != nextin) { 593 1.1 kamil *addr = circlebuf[nextout++]; 594 1.1 kamil nextout %= PUSHSIZE; 595 1.1 kamil return 1; 596 1.1 kamil } 597 1.1 kamil else { 598 1.1 kamil size = read(0,addr,1); 599 1.1 kamil if (size < 0) 600 1.1 kamil sig_catcher(SIGHUP); 601 1.1 kamil if (metakey) { 602 1.1 kamil if (*addr & 0200) { 603 1.1 kamil pushchar(*addr & 0177); 604 1.1 kamil *addr = '\001'; 605 1.1 kamil } 606 1.1 kamil } 607 1.1 kamil else 608 1.1 kamil *addr &= 0177; 609 1.1 kamil return 1; 610 1.1 kamil } 611 1.1 kamil } 612 1.1 kamil 613 1.1 kamil #ifdef PENDING 614 1.1 kamil #ifndef FIONREAD 615 1.1 kamil #ifndef RDCHK 616 1.1 kamil int 617 1.1 kamil circfill() 618 1.1 kamil { 619 1.4 christos int howmany; 620 1.4 christos int i; 621 1.1 kamil 622 1.1 kamil assert (nextin == nextout); 623 1.1 kamil howmany = read(devtty,circlebuf+nextin,metakey?1:PUSHSIZE-nextin); 624 1.1 kamil if (howmany > 0) { 625 1.1 kamil if (metakey) { 626 1.1 kamil if (circlebuf[nextin] & 0200) { 627 1.1 kamil circlebuf[nextin] &= 0177; 628 1.1 kamil pushchar('\001'); 629 1.1 kamil } 630 1.1 kamil } 631 1.1 kamil else 632 1.1 kamil for (i = howmany+nextin-1; i >= nextin; i--) 633 1.1 kamil circlebuf[i] &= 0177; 634 1.1 kamil nextin += howmany; 635 1.1 kamil nextin %= PUSHSIZE; /* may end up 1 if metakey */ 636 1.1 kamil } 637 1.1 kamil return howmany; 638 1.1 kamil } 639 1.1 kamil #endif /* RDCHK */ 640 1.1 kamil #endif /* FIONREAD */ 641 1.1 kamil #endif /* PENDING */ 642 1.1 kamil 643 1.1 kamil void 644 1.4 christos pushchar(int ch) 645 1.1 kamil { 646 1.1 kamil nextout--; 647 1.1 kamil if (nextout < 0) 648 1.1 kamil nextout = PUSHSIZE - 1; 649 1.1 kamil if (nextout == nextin) { 650 1.1 kamil fputs("\r\npushback buffer overflow\r\n",stdout); 651 1.1 kamil sig_catcher(0); 652 1.1 kamil } 653 1.1 kamil circlebuf[nextout] = ch; 654 1.1 kamil } 655 1.1 kamil 656 1.1 kamil #else /* PUSHBACK */ 657 1.1 kamil #ifndef read_tty 658 1.1 kamil /* read a character from the terminal, with hacks for O_NDELAY reads */ 659 1.1 kamil 660 1.1 kamil int 661 1.1 kamil read_tty(addr,size) 662 1.1 kamil char *addr; 663 1.1 kamil int size; 664 1.1 kamil { 665 1.1 kamil if (is_input) { 666 1.1 kamil *addr = pending_ch; 667 1.4 christos is_input = false; 668 1.1 kamil return 1; 669 1.1 kamil } 670 1.1 kamil else { 671 1.1 kamil size = read(0,addr,size); 672 1.1 kamil if (size < 0) 673 1.1 kamil sig_catcher(SIGHUP); 674 1.1 kamil if (metakey) { 675 1.1 kamil if (*addr & 0200) { 676 1.1 kamil pending_ch = *addr & 0177; 677 1.4 christos is_input = true; 678 1.1 kamil *addr = '\001'; 679 1.1 kamil } 680 1.1 kamil } 681 1.1 kamil else 682 1.1 kamil *addr &= 0177; 683 1.1 kamil return size; 684 1.1 kamil } 685 1.1 kamil } 686 1.1 kamil #endif /* read_tty */ 687 1.1 kamil #endif /* PUSHBACK */ 688 1.1 kamil 689 1.1 kamil int 690 1.4 christos read_nd(char *buff, size_t siz) 691 1.1 kamil { 692 1.1 kamil if (!input_pending()) 693 1.1 kamil return 0; 694 1.1 kamil 695 1.1 kamil getcmd(buff); 696 1.1 kamil return 1; 697 1.1 kamil } 698 1.1 kamil 699 1.1 kamil /* get a character into a buffer */ 700 1.1 kamil 701 1.1 kamil void 702 1.4 christos getcmd(char *wbuf) 703 1.1 kamil { 704 1.1 kamil #ifdef PUSHBACK 705 1.4 christos KEYMAP *curmap; 706 1.4 christos int i; 707 1.8 rillig bool no_macros; 708 1.1 kamil int times = 0; /* loop detector */ 709 1.1 kamil char scrchar; 710 1.4 christos unsigned char *whatbuf = (void *)wbuf; 711 1.1 kamil 712 1.1 kamil tryagain: 713 1.1 kamil curmap = topmap; 714 1.1 kamil /* no_macros = (whatbuf != buf && nextin == nextout); */ 715 1.4 christos no_macros = false; 716 1.1 kamil #endif 717 1.1 kamil for (;;) { 718 1.1 kamil errno = 0; 719 1.4 christos if (read_tty(wbuf,1) < 0 && !errno) 720 1.1 kamil errno = EINTR; 721 1.1 kamil #ifdef read_tty 722 1.1 kamil if (metakey) { 723 1.1 kamil if (*whatbuf & 0200) { 724 1.1 kamil *what_buf &= 037; /* punt and hope they don't notice */ 725 1.1 kamil } 726 1.1 kamil } 727 1.1 kamil else 728 1.1 kamil *whatbuf &= 0177; 729 1.1 kamil #endif /* read_tty */ 730 1.1 kamil if (errno && errno != EINTR) { 731 1.1 kamil perror(readerr); 732 1.1 kamil sig_catcher(0); 733 1.1 kamil } 734 1.1 kamil #ifdef PUSHBACK 735 1.1 kamil if (*whatbuf & 0200 || no_macros) { 736 1.1 kamil *whatbuf &= 0177; 737 1.1 kamil goto got_canonical; 738 1.1 kamil } 739 1.4 christos if (curmap == NULL) 740 1.1 kamil goto got_canonical; 741 1.1 kamil for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){ 742 1.4 christos read_tty(&scrchar,1); 743 1.1 kamil } 744 1.1 kamil switch (curmap->km_type[*whatbuf] & KM_TMASK) { 745 1.1 kamil case KM_NOTHIN: /* no entry? */ 746 1.1 kamil if (curmap == topmap) /* unmapped canonical */ 747 1.1 kamil goto got_canonical; 748 1.1 kamil settle_down(); 749 1.1 kamil goto tryagain; 750 1.1 kamil case KM_KEYMAP: /* another keymap? */ 751 1.1 kamil curmap = curmap->km_ptr[*whatbuf].km_km; 752 1.4 christos assert(curmap != NULL); 753 1.1 kamil break; 754 1.1 kamil case KM_STRING: /* a string? */ 755 1.1 kamil pushstring(curmap->km_ptr[*whatbuf].km_str); 756 1.1 kamil if (++times > 20) { /* loop? */ 757 1.1 kamil fputs("\r\nmacro loop?\r\n",stdout); 758 1.1 kamil settle_down(); 759 1.1 kamil } 760 1.4 christos no_macros = false; 761 1.1 kamil goto tryagain; 762 1.1 kamil } 763 1.1 kamil #else 764 1.1 kamil *whatbuf &= 0177; 765 1.1 kamil break; 766 1.1 kamil #endif 767 1.1 kamil } 768 1.1 kamil 769 1.1 kamil got_canonical: 770 1.6 christos #if !defined(TERMIO) && !defined(TERMIOS) 771 1.1 kamil if (*whatbuf == '\r') 772 1.1 kamil *whatbuf = '\n'; 773 1.1 kamil #endif 774 1.4 christos if (wbuf == buf) 775 1.1 kamil whatbuf[1] = FINISHCMD; /* tell finish_command to work */ 776 1.1 kamil } 777 1.1 kamil 778 1.1 kamil #ifdef PUSHBACK 779 1.1 kamil void 780 1.4 christos pushstring(char *str) 781 1.1 kamil { 782 1.4 christos int i; 783 1.1 kamil char tmpbuf[PUSHSIZE]; 784 1.4 christos char *s = tmpbuf; 785 1.1 kamil 786 1.4 christos assert(str != NULL); 787 1.1 kamil interp(s,PUSHSIZE,str); 788 1.1 kamil for (i = strlen(s)-1; i >= 0; --i) { 789 1.8 rillig s[i] ^= 0200; 790 1.1 kamil pushchar(s[i]); 791 1.1 kamil } 792 1.1 kamil } 793 1.1 kamil #endif 794