1 /* 2 * Various input/output functions 3 * 4 * io.c 1.4 (A.I. Design) 12/10/84 5 */ 6 7 #include "rogue.h" 8 #include "curses.h" 9 #include "extern.h" 10 11 extern char *stccpy(), *stpchr(); 12 extern int scr_type; 13 extern unsigned tick; 14 15 #define AC(a) (-((a)-11)) 16 char *stpbrk(); 17 #define PT(i,j) ((COLS==40)?i:j) 18 /* 19 * msg: 20 * Display a message at the top of the screen. 21 */ 22 extern char *msgbuf; 23 static int newpos = 0; 24 25 /* VARARGS1 */ 26 27 ifterse(tfmt,fmt,a1,a2,a3,a4,a5) 28 char *tfmt,*fmt; 29 int a1,a2,a3,a4,a5; 30 { 31 if (expert) 32 msg(tfmt,a1,a2,a3,a4,a5); 33 else 34 msg(fmt,a1,a2,a3,a4,a5); 35 } 36 37 msg(fmt, a1, a2, a3, a4, a5) 38 char *fmt; 39 int a1,a2,a3,a4,a5; 40 { 41 /* 42 * if the string is "", just clear the line 43 */ 44 if (*fmt == '\0') 45 { 46 move(0, 0); 47 clrtoeol(); 48 mpos = 0; 49 return; 50 } 51 /* 52 * otherwise add to the message and flush it out 53 */ 54 doadd(fmt, a1,a2,a3,a4,a5); 55 endmsg(); 56 } 57 58 /* 59 * addmsg: 60 * Add things to the current message 61 */ 62 /* VARARGS1 */ 63 addmsg(fmt, a1,a2,a3,a4,a5) 64 char *fmt; 65 int a1,a2,a3,a4,a5; 66 { 67 doadd(fmt, a1,a2,a3,a4,a5); 68 } 69 70 /* 71 * endmsg: 72 * Display a new msg (giving him a chance to see the previous one 73 * if it is up there with the -More-) 74 */ 75 endmsg() 76 { 77 if (save_msg) 78 strcpy(huh, msgbuf); 79 if (mpos) { 80 look(FALSE); 81 move(0,mpos); 82 more(" More "); 83 } 84 /* 85 * All messages should start with uppercase, except ones that 86 * start with a pack addressing character 87 */ 88 if (islower(msgbuf[0]) && msgbuf[1] != ')') 89 msgbuf[0] = toupper(msgbuf[0]); 90 putmsg(0,msgbuf); 91 mpos = newpos; 92 newpos = 0; 93 } 94 95 96 /* 97 * More: tag the end of a line and wait for a space 98 */ 99 more(msg) 100 char *msg; 101 { 102 int x, y; 103 register int i, msz; 104 char mbuf[80]; 105 int morethere = TRUE; 106 int covered = FALSE; 107 108 msz = strlen(msg); 109 getxy(&x,&y); 110 /* 111 * it is reasonable to assume that if the you are no longer 112 * on line 0, you must have wrapped. 113 */ 114 if (x != 0) { 115 x=0; 116 y=COLS; 117 } 118 if ((y+msz)>COLS) { 119 move(x,y=COLS-msz); 120 covered = TRUE; 121 } 122 123 for(i=0;i COLS) { 184 more(" Cont "); 185 lastmsg = curmsg; 186 do { 187 tmpmsg = stpbrk(curmsg," "); 188 /* 189 * If there are no blanks in line 190 */ 191 if ((tmpmsg==0 || tmpmsg>=&lastmsg[COLS]) && lastmsg==curmsg) { 192 curmsg = &lastmsg[COLS]; 193 break; 194 } 195 if ((tmpmsg >= (lastmsg+COLS)) || (strlen(curmsg) < COLS)) 196 break; 197 curmsg = tmpmsg + 1; 198 } while (1) ; 199 } 200 } while (curlen > COLS) ; 201 } 202 203 /* 204 * scrl: scroll a message accross the line 205 */ 206 scrl(msgline,str1,str2) 207 int msgline; 208 char *str1, *str2; 209 { 210 char *fmt; 211 register int x,y; 212 213 if (COLS > 40) 214 fmt = "%.80s"; 215 else 216 fmt = "%.40s"; 217 218 if (str1 == 0) { 219 move(msgline,0); 220 if (strlen(str2) < COLS) 221 clrtoeol(); 222 printw(fmt,str2); 223 } else 224 while (str1 <= str2) { 225 move(msgline,0); 226 printw(fmt,str1++); 227 if (strlen(str1) < (COLS-1)) 228 clrtoeol(); 229 } 230 } 231 232 /* 233 * unctrl: 234 * Print a readable version of a certain character 235 */ 236 char * 237 unctrl(ch) 238 unsigned char ch; 239 { 240 static chstr[9]; /* Defined in curses library */ 241 242 if (isspace(ch) ) 243 strcpy(chstr," "); 244 else if (!isprint(ch)) 245 if (ch < ' ') 246 sprintf(chstr, "^%c", ch + '@'); 247 else 248 sprintf(chstr, "\\x%x",ch); 249 else { 250 chstr[0] = ch; 251 chstr[1] = 0; 252 } 253 254 return chstr; 255 } 256 257 /* 258 * status: 259 * Display the important stats line. Keep the cursor where it was. 260 */ 261 status() 262 { 263 int oy, ox; 264 static int s_hungry; 265 static int s_lvl, s_pur = -1, s_hp, s_ac = 0; 266 static str_t s_str; 267 static int s_elvl = 0; 268 static char *state_name[] = 269 { 270 " ", "Hungry", "Weak", "Faint","?" 271 }; 272 273 SIG2(); 274 275 getyx(stdscr, oy, ox); 276 if (is_color) 277 yellow(); 278 279 /* 280 * Level: 281 */ 282 if (s_lvl != level) 283 { 284 s_lvl = level; 285 move(PT(22,23),0); 286 printw("Level:%-4.4d", level); 287 } 288 289 /* 290 * Hits: 291 */ 292 if (s_hp != pstats.s_hpt) 293 { 294 s_hp = pstats.s_hpt; 295 move(PT(22,23),12); 296 printw("Hits:%.3d(%.3d) ", pstats.s_hpt, max_hp); 297 /* just in case they get wraithed with 3 digit max hits */ 298 if (pstats.s_hpt < 100) 299 addch(' '); 300 } 301 302 /* 303 * Str: 304 */ 305 if (pstats.s_str != s_str) 306 { 307 s_str = pstats.s_str; 308 move(PT(22,23),26); 309 printw("Str:%.3d(%.3d) ", pstats.s_str, max_stats.s_str); 310 } 311 312 /* 313 * Gold 314 */ 315 if(s_pur != purse) 316 { 317 s_pur = purse; 318 move(23, PT(0,40)); 319 printw("Gold:%-5.5u",purse); 320 } 321 322 /* 323 * Armor: 324 */ 325 if(s_ac != (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm)) 326 { 327 s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm); 328 if (ISRING(LEFT,R_PROTECT)) 329 s_ac -= cur_ring[LEFT]->o_ac; 330 if (ISRING(RIGHT,R_PROTECT)) 331 s_ac -= cur_ring[RIGHT]->o_ac; 332 move(23,PT(12,52)); 333 printw("Armor:%-2.2d", 334 AC(cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm)); 335 } 336 337 /* 338 * Exp: 339 */ 340 if (s_elvl != pstats.s_lvl) 341 { 342 s_elvl = pstats.s_lvl; 343 move(23, PT(22, 62)); 344 printw("%-12s", he_man[s_elvl-1]); 345 } 346 347 /* 348 * Hungry state 349 */ 350 if (s_hungry != hungry_state) 351 { 352 s_hungry = hungry_state; 353 move(24, PT(28,58)); 354 addstr(state_name[0]); 355 move(24, PT(28,58)); 356 if (hungry_state) 357 { 358 bold(); 359 addstr(state_name[hungry_state]); 360 standend(); 361 } 362 } 363 364 if (is_color) 365 standend(); 366 367 move(oy, ox); 368 369 } 370 371 /* 372 * wait_for 373 * Sit around until the guy types the right key 374 */ 375 wait_for(ch) 376 char ch; 377 { 378 register char c; 379 380 if (ch == '\n') 381 while ((c = readchar()) != '\n' && c != '\r') 382 continue; 383 else 384 while (readchar() != ch) 385 continue; 386 } 387 388 /* 389 * show_win: 390 * Function used to display a window and wait before returning 391 */ 392 show_win(scr, message) 393 int *scr; 394 char *message; 395 { 396 mvaddstr(0,0,message); 397 move(hero.y, hero.x); 398 wait_for(' '); 399 } 400 401 402 /* 403 * This routine reads information from the keyboard 404 * It should do all the strange processing that is 405 * needed to retrieve sensible data from the user 406 */ 407 getinfo(str,size) 408 char *str; 409 int size; 410 { 411 register char *retstr, ch; 412 int readcnt = 0; 413 int wason, ret = 1; 414 char buf[160]; 415 416 dmain(buf, 80, scr_ds, 0); 417 retstr = str; 418 *str = 0; 419 wason = cursor(TRUE); 420 while(ret == 1) 421 switch(ch = getch()) { 422 case ESCAPE: 423 while(str != retstr) { 424 backspace(); 425 readcnt--; 426 str--; 427 } 428 ret = *str = ESCAPE; 429 cursor(wason); 430 break; 431 case '\b': 432 if (str != retstr) { 433 backspace(); 434 readcnt--; 435 str--; 436 } 437 break; 438 default: 439 if ( readcnt >= size) { 440 beep(); 441 break; 442 } 443 readcnt++; 444 addch(ch); 445 *str++ = ch; 446 if ((ch & 0x80) == 0) 447 break; 448 case '\n': 449 case '\r': 450 *str = 0; 451 cursor(wason); 452 ret = ch; 453 break; 454 } 455 dmaout(buf, 80, scr_ds, 0); 456 return ret; 457 } 458 459 backspace() 460 { 461 int x, y; 462 getxy(&x,&y); 463 if (--y<0) 464 y = 0; 465 move(x,y); 466 putchr(' '); 467 } 468 469 /* 470 * str_attr: format a string with attributes. 471 * 472 * formats: 473 * %i - the following character is turned inverse vidio 474 * %I - All characters upto %$ or null are turned inverse vidio 475 * %u - the following character is underlined 476 * %U - All characters upto %$ or null are underlined 477 * %$ - Turn off all attributes 478 * 479 * Attributes do not nest, therefore turning on an attribute while 480 * a different one is in effect simply changes the attribute. 481 * 482 * "No attribute" is the default and is set on leaving this routine 483 * 484 * Eventually this routine will contain colors and character intensity 485 * attributes. And I'm not sure how I'm going to interface this with 486 * printf certainly '%' isn't a good choice of characters. jll. 487 */ 488 str_attr(str) 489 char *str; 490 { 491 #ifdef LUXURY 492 register int is_attr_on = FALSE, was_touched = FALSE; 493 494 while(*str) 495 { 496 if (was_touched == TRUE) 497 { 498 standend(); 499 is_attr_on = FALSE; 500 was_touched = FALSE; 501 } 502 if (*str == '%') 503 { 504 str++; 505 switch(*str) 506 { 507 case 'u': 508 was_touched = TRUE; 509 case 'U': 510 uline(); 511 is_attr_on = TRUE; 512 str++; 513 break; 514 case 'i': 515 was_touched = TRUE; 516 case 'I': 517 standout(); 518 is_attr_on = TRUE; 519 str++; 520 break; 521 case '$': 522 if (is_attr_on) 523 was_touched = TRUE; 524 str++; 525 continue; 526 } 527 } 528 if ((*str == '\n') || (*str == '\r')) 529 { 530 str++; 531 printw("\n"); 532 } 533 else if (*str != 0) 534 addch(*str++); 535 } 536 if (is_attr_on) 537 standend(); 538 #else 539 while (*str) 540 { 541 if (*str == '%') { 542 str++; 543 standout(); 544 } 545 addch(*str++); 546 standend(); 547 } 548 549 #endif LUXURY 550 } 551 552 /* 553 * key_state: 554 */ 555 SIG2() 556 { 557 static unsigned icnt = 0, ntick = 0; 558 static int key_init = TRUE; 559 static int numl, capsl; 560 static int nspot, cspot, tspot; 561 register int new_numl, new_capsl, new_fmode; 562 static int bighand, littlehand; 563 int showtime = FALSE, spare; 564 int x, y; 565 char wbuf[10]; 566 #ifdef DEMO 567 static tot_time = 0; 568 #endif DEMO 569 570 if (tick < ntick) 571 return; 572 ntick = tick + 6; 573 if (is_saved || scr_type < 0) 574 return; 575 regs->ax = 0x200; 576 swint(SW_KEY, regs); 577 new_numl = regs->ax; 578 new_capsl = new_numl & 0x40; 579 new_fmode = new_numl & 0x10; 580 new_numl &= 0x20; 581 /* 582 * set up the clock the first time here 583 */ 584 if (key_init) { 585 regs->ax = 0x2c << 8; 586 swint(SW_DOS, regs); 587 bighand = (regs->cx >> 8) % 12; 588 littlehand = regs->cx & 0xFF; 589 showtime++; 590 } 591 if (tick > 1092) { 592 /* 593 * time os call kills jr and others we keep track of it 594 * ourselves 595 */ 596 littlehand = (littlehand + 1) % 60; 597 if (littlehand == 0) 598 bighand = (bighand + 1) % 12; 599 tick = tick - 1092; 600 ntick = tick + 6; 601 showtime++; 602 } 603 604 /* 605 * this is built for speed so set up once first time this 606 * is executed 607 */ 608 if (key_init || reinit) 609 { 610 reinit = key_init = FALSE; 611 if (COLS == 40) 612 { 613 nspot = 10; 614 cspot = 19; 615 tspot = 35; 616 } 617 else 618 { 619 nspot = 20; 620 cspot = 39; 621 tspot = 75; 622 } 623 /* 624 * this will force all fields to be updated first time through 625 */ 626 numl = !new_numl; 627 capsl = !new_capsl; 628 showtime++; 629 faststate = !new_fmode; 630 } 631 632 getxy(&x, &y); 633 634 if (faststate != new_fmode) 635 { 636 637 faststate = new_fmode; 638 count = 0; 639 show_count(); 640 running = FALSE; 641 move(LINES-1,0); 642 if (faststate) 643 { 644 bold(); 645 addstr("Fast Play"); 646 standend(); 647 } 648 else 649 { 650 addstr(" "); 651 } 652 } 653 654 if (numl != new_numl) 655 { 656 numl = new_numl; 657 count = 0; 658 show_count(); 659 running = FALSE; 660 move(24,nspot); 661 if (numl) 662 { 663 bold(); 664 addstr("NUM LOCK"); 665 standend(); 666 } 667 else 668 addstr(" "); 669 } 670 if (capsl != new_capsl) 671 { 672 capsl = new_capsl; 673 move(24,cspot); 674 if (capsl) 675 { 676 bold(); 677 addstr("CAP LOCK"); 678 standend(); 679 } 680 else 681 addstr(" "); 682 } 683 if (showtime) 684 { 685 showtime = FALSE; 686 #ifdef DEMO 687 /* 688 * Don't let them get by level 10 because they might do something 689 * nasty like disable the clock 690 */ 691 if (((tot_time++ - max_level) > DEMOTIME) || max_level > 10) 692 demo(DEMOTIME); 693 #endif DEMO 694 /* work around the compiler buggie boos */ 695 spare = littlehand % 10; 696 move(24,tspot); 697 bold(); 698 printw("%2d:%1d%1d",bighand?bighand:12,littlehand/10,spare); 699 standend(); 700 } 701 move(x, y); 702 } 703 704 /* 705 * Replacement printf 706 * Michael Toy, AI Design, January 1984 707 */ 708 709 static int pf_str(), pf_chr(), pf_uint(), pf_int(), pf_per(); 710 static char *formats = "scud%", *bp, left_justify; 711 static int min_width, max_width; 712 713 static int (*(pfuncs[]))() = { 714 pf_str, pf_chr, pf_uint, pf_int, pf_per 715 }; 716 717 char *my_stccpy(a, b, c) 718 { 719 stccpy(a, b, c); 720 return a + strlen(a); 721 } 722 723 char * 724 sprintf(buf, fmt, arg) 725 char *buf, *fmt; 726 int arg; 727 { 728 register char *cp, *init; 729 int *ap = &arg, pad; 730 char tbuf[128]; 731 732 init = buf; 733 while (*fmt) { 734 if (*fmt != '%') 735 *buf++ = *fmt++; 736 else { 737 left_justify = max_width = 0; 738 if (*++fmt == '-') 739 left_justify++, fmt++; 740 min_width = scan_num(fmt); 741 if (*bp == '.') 742 max_width = scan_num(++bp); 743 fmt = bp; 744 bp = tbuf; 745 if (cp = stpchr(formats, *fmt)) 746 ap += (*(pfuncs[cp - formats]))(ap); 747 *bp = 0; 748 if (max_width && strlen(tbuf) > max_width) 749 tbuf[max_width] = 0; 750 pad = min_width - strlen(tbuf); 751 bp = buf; 752 if (!left_justify) 753 blanks(pad); 754 bp = my_stccpy(bp, tbuf, 200); 755 if (left_justify) 756 blanks(pad); 757 buf = bp; 758 if (*fmt) 759 fmt++; 760 } 761 } 762 *buf = 0; 763 return init; 764 } 765 766 scan_num(cp) 767 char *cp; 768 { 769 register int i = 0; 770 771 bp = cp; 772 while (isdigit(*bp)) 773 i = i * 10 + *bp++ - '0'; 774 return i; 775 } 776 777 pf_str(cp) 778 char **cp; 779 { 780 bp = my_stccpy(bp, *cp, 200); 781 return 1; 782 } 783 784 blanks(cnt) 785 { 786 while (cnt-- > 0) 787 *bp++ = ' '; 788 *bp = 0; 789 } 790 791 pf_chr(c) 792 char *c; 793 { 794 *bp++ = *c; 795 return 1; 796 } 797 798 static char ibuf[6]; 799 800 pf_int(ip) 801 int *ip; 802 { 803 if (*ip < 0) { 804 *bp++ = '-'; 805 *ip = (-*ip); 806 } 807 return pf_uint(ip); 808 } 809 810 pf_uint(ip) 811 unsigned int *ip; 812 { 813 char *cp = ibuf, once; 814 unsigned int i = *ip, d = 10000, r; 815 816 if (*ip == 0) { 817 *ibuf = '0'; 818 ibuf[1] = 0; 819 } else { 820 once = 0; 821 while (d) { 822 if ((r = i/d) || once) { 823 *cp++ = r + '0'; 824 once =1; 825 i -= r*d; 826 } 827 d /= 10; 828 } 829 *cp = 0; 830 } 831 bp = my_stccpy(bp, ibuf, 6); 832 return 1; 833 } 834 835 pf_per(ip) 836 { 837 *bp++ = '%'; 838 return 0; 839 } 840 841 noterse(str) 842 char *str; 843 { 844 return( terse || expert ? nullstr : str); 845 } 846 847 ÿ