/* omega (c) 1987,1988,1989 by Laurence Raphael Brothers */ /* scr.c */ /* functions that use curses routines directly */ /* plus a few file i/o stuff */ /* also some in file.c */ #ifdef MSDOS_SUPPORTED_ANTIQUE # include "curses.h" #else # ifdef AMIGA # include # elif defined(USE_OPCURSES) # include "../opcurses/curses.h" # else # include # endif # include #endif #if defined(MSDOS_SUPPORTED_ANTIQUE) || defined(AMIGA) # define CHARATTR(c) ((c) >> 8) #else # define CHARATTR(c) ((c) & ~0xff) #endif #include "glob.h" #include #include #ifdef EXCESSIVE_REDRAW #undef wclear #define wclear werase #endif #ifdef NEW_BANK WINDOW *Bankw; #endif /* note these variables are not exported to other files */ WINDOW *Levelw,*Dataw,*Flagw,*Timew,*Menuw,*Locw,*Morew,*Phasew; WINDOW *Comwin,*Msg1w,*Msg2w,*Msg3w,*Msgw; WINDOW *Cinema; /* WDT: interactions and special effects which currently * go into the message window should instead go here. This * should simplify history-keeping, since we only need to * record actual messages, not special effects. */ WINDOW *Showline[MAXITEMS]; #define SL3_LEN 160 char screenLine3[SL3_LEN]; /* static function prototypes */ static long input_number (WINDOW * w); /* function definitions */ void phaseprint(void) { wclear(Phasew); wprintw(Phasew,"Moon's Phase:\n"); switch(Phase/2) { case 0: wprintw(Phasew,"NEW"); break; case 1: case 11: wprintw(Phasew,"CRESCENT"); break; case 2: case 10: wprintw(Phasew,"1/4"); break; case 3: case 9: wprintw(Phasew,"HALF"); break; case 4: case 8: wprintw(Phasew,"3/4"); break; case 5: case 7: wprintw(Phasew,"GIBBOUS"); break; case 6: wprintw(Phasew,"FULL"); break; } wrefresh(Phasew); } static void show_screen_level (int top, int left, int bottom, int right) { int j; int last_attr = 0; for (j = top; j < bottom; ++j) { int i; wmove(Levelw, screenmody(j), 0); for (i = left; i < right; ++i) { int c; if (loc_statusp(i, j, SEEN)) c = getspot(i, j, FALSE); else c = SPACE; if (optionp(SHOW_COLOUR) && CHARATTR(c) != last_attr) { last_attr = CHARATTR(c); wattrset(Levelw, last_attr); } waddch(Levelw, c & 0xff); } } } static void show_screen_country (int top, int left, int bottom, int right) { int j; int last_attr = 0; for (j = top; j < bottom; ++j) { int i; wmove(Levelw, screenmody(j), 0); for (i = left; i < right; ++i) { int c; if (c_statusp(i, j, SEEN)) c = Country[i][j].current_terrain_type; else c = SPACE; if (optionp(SHOW_COLOUR) && CHARATTR(c) != last_attr) { last_attr = CHARATTR(c); wattrset(Levelw, last_attr); } waddch(Levelw, c & 0xff); } } } void show_screen(void) { int top; int left; int right; int bottom; wclear(Levelw); if (ScreenOffset < 0) ScreenOffset = 0; if (ScreenXOffset < 0) ScreenXOffset = 0; top = ScreenOffset; left = ScreenXOffset; right = ScreenXOffset + ScreenWidth; bottom = ScreenOffset + ScreenLength; if (Current_Environment != E_COUNTRYSIDE) { if (right > Level->level_width) right = Level->level_width; if (bottom > Level->level_length) bottom = Level->level_length; } else { if (right > COUNTRY_WIDTH) right = COUNTRY_WIDTH; if (bottom > COUNTRY_LENGTH) bottom = COUNTRY_LENGTH; } if (Current_Environment != E_COUNTRYSIDE) { show_screen_level(top, left, bottom, right); } else { show_screen_country(top, left, bottom, right); #if 0 for (j=top;j=(int)'A') && (c<=(int)'Z')) return(c+(int)('a'-'A')); else return(c); } char menugetc(void) { return(wgetch(Menuw)); } char lgetc(void) { return(wgetch(Levelw)); } int ynq(void) { int p='*'; /* the user's choice; start with something impossible * to prevent a loop. */ while ((p != 'n') && (p != 'y') && (p != 'q') && (p != ESCAPE) && (p != EOF) && (p != ' ')) p = wgetch(Msgw); switch (p) { case 'y': wprintw(Msgw,"yes. "); break; case 'n': wprintw(Msgw,"no. "); break; case ESCAPE: p = 'q'; /* fall through to 'q' */ case ' ': p = 'q'; /* fall through to 'q' */ case 'q': wprintw(Msgw,"quit. "); break; default: assert( p == EOF ); } wrefresh(Msgw); return(p); } int ynq1(void) { int p='*'; /* the user's choice; start with something impossible * to prevent a loop. */ while ((p != 'n') && (p != 'y') && (p != 'q') && (p != ESCAPE) && (p != ' ') && (p != EOF)) p = wgetch(Msg1w); switch (p) { case 'y': wprintw(Msg1w,"yes. "); break; case 'n': wprintw(Msg1w,"no. "); break; case ESCAPE: p = 'q'; /* fall through to 'q' */ case ' ': p = 'q'; /* fall through to 'q' */ case 'q': wprintw(Msg1w,"quit. "); break; default: assert( p == EOF ); } wrefresh(Msg1w); return(p); } int ynq2(void) { int p='*'; /* the user's choice; start with something impossible * to prevent a loop. */ while ((p != 'n') && (p != 'y') && (p != 'q') && (p != ESCAPE) && (p != ' ') && (p != EOF)) p = wgetch(Msg2w); switch (p) { case 'y': wprintw(Msg2w,"yes. "); break; case 'n': wprintw(Msg2w,"no. "); break; case ESCAPE: p = 'q'; /* fall through to 'q' */ case ' ': p = 'q'; /* fall through to 'q' */ case 'q': wprintw(Msg2w,"quit. "); break; default: assert( p == EOF ); } wrefresh(Msg2w); return(p); } void erasemsg3 (void) { werase(Msg3w); memset(screenLine3, 0, SL3_LEN); } /* puts up a morewait to allow reading if anything in top two lines */ void checkclear(void) { int x1,y,x2; getyx(Msg1w,x1,y); getyx(Msg2w,x2,y); if ((x1 != 0) || (x2 != 0)) { morewait(); wclear(Msg1w); wclear(Msg2w); wrefresh(Msg1w); wrefresh(Msg2w); } } /* for external call */ void clearmsg(void) { wclear(Msg1w); wclear(Msg2w); erasemsg3(); Msgw = Msg1w; wrefresh(Msg1w); wrefresh(Msg2w); wrefresh(Msg3w); } void clearmsg3(void) { erasemsg3(); wrefresh(Msg3w); } void clearmsg1(void) { wclear(Msg1w); wclear(Msg2w); Msgw = Msg1w; wrefresh(Msg1w); wrefresh(Msg2w); } void erase_level(void) { wclear(Levelw); wrefresh(Levelw); } /* direct print to first msg line */ void print1(char *s) { if (! gamestatusp(SUPPRESS_PRINTING)) { buffercycle(s); wclear(Msg1w); wprintw(Msg1w,s); wrefresh(Msg1w); } } /* for run on-messages -- print1 clears first.... */ void nprint1(char *s) { if (! gamestatusp(SUPPRESS_PRINTING)) { if (bufferappend(s)) { wprintw(Msg1w,s); wrefresh(Msg1w); } } } /* direct print to second msg line */ void print2(char *s) { if (! gamestatusp(SUPPRESS_PRINTING)) { buffercycle(s); wclear(Msg2w); wprintw(Msg2w,s); wrefresh(Msg2w); } } /* for run on-messages -- print2 clears first.... */ void nprint2(char *s) { if (! gamestatusp(SUPPRESS_PRINTING)) { if (bufferappend(s)) { wprintw(Msg2w,s); wrefresh(Msg2w); } } } /* msg line 3 is not part of the region that mprint or printm can reach */ /* typical use of print3 is for "you can't do that" type error messages */ /* WDT: it's also typically used for messages intended to persist a while. * Thus I'm having print3 save its input in a global variable which other * things can use. */ void print3 (char *s) { if (!gamestatusp(SUPPRESS_PRINTING)) { buffercycle(s); erasemsg3(); wprintw(Msg3w, s); strcpy(screenLine3, s); wrefresh(Msg3w); } } /* for run on-messages -- print3 clears first.... */ void nprint3(char *s) { if (!gamestatusp(SUPPRESS_PRINTING)) { if (bufferappend(s)) { strcat(screenLine3, s); wprintw(Msg3w,s); wrefresh(Msg3w); } } } /* prints wherever cursor is in window, but checks to see if it should morewait and clear window */ void mprint(char *s) { int x,y; if (! gamestatusp(SUPPRESS_PRINTING)) { getyx(Msgw,y,x); if (x+strlen(s) >= ScreenWidth) { buffercycle(s); if (Msgw == Msg1w) { wclear(Msg2w); Msgw = Msg2w; } else { morewait(); wclear(Msg1w); wclear(Msg2w); wrefresh(Msg2w); Msgw = Msg1w; } } else if (x > 0) bufferappend(s); else buffercycle(s); wprintw(Msgw,s); waddch(Msgw,' '); wrefresh(Msgw); } } void omega_title(void) { showmotd(); clear(); touchwin(stdscr); refresh(); /* showscores();*/ /* DG */ } /* blanks out ith line of Menuw or Levelw */ void hide_line(int i) { wclear(Showline[i]); touchwin(Showline[i]); wrefresh(Showline[i]); } #ifdef USE_OPCURSES static void load_tiles (void) { char * path; path = malloc(strlen(OMEGALIB) + strlen(TILEFILE) + 1); if (0 == path) return; strcpy(path, OMEGALIB); strcat(path, TILEFILE); set_tiles(path); free(path); } #endif /* initialize, screen, windows */ void initgraf(void) { int i; #ifdef USE_OPCURSES load_tiles(); #endif initscr(); #if !defined(MSDOS_SUPPORTED_ANTIQUE) start_color(); # ifndef AMIGA clrgen_init(); # endif #endif if (LINES < 24 || COLS < 80) { printf("Minimum Screen Size: 24 Lines by 80 Columns."); exit(0); } #ifdef AMIGA init_color(1, 800, 800, 800); /* white */ init_color(2, 644, 164, 164); /* brown */ init_color(3, 800, 800, 0); /* yellow */ init_color(4, 200, 200, 200); /* grey */ init_color(5, 0, 1000, 0); /* green */ init_color(6, 0, 0, 1000); /* blue */ init_color(7, 1000, 0, 0); /* red */ LINES -= 2; /* ugly, but neccessary with this curses package... */ #endif ScreenLength = LINES - 6; ScreenWidth = 64; /* PGM */ Msg1w = newwin(1,80,0,0); scrollok(Msg1w, 0); /* DJGPP curses defaults to scrollable new windows */ Msg2w = newwin(1,80,1,0); scrollok(Msg2w, 0); Msg3w = newwin(1,80,2,0); scrollok(Msg3w, 0); Msgw = Msg1w; Morew = newwin(1,15,3,65); scrollok(Morew, 0); #ifdef NEW_BANK Bankw = newwin( 20, 50, ( ScreenLength - 20 ) / 2 + 3, 7 ); scrollok( Bankw, 0 ); #endif Locw = newwin(1,80,ScreenLength+3,0); scrollok(Locw, 0); Levelw = newwin(ScreenLength,ScreenWidth,3,0); scrollok(Levelw, 0); for(i=0;i 0); while (1) { cinema_display(line1, line2, line3); response = cinema_getch(); if (-1 == response) break; if (strchr(choices, response)) break; if (!line3) line3 = "What? Try again!"; } cinema_hide(); return response; } int cinema_interact_line (int line, char * choices, char * text) { int response; assert(0 == line || 1 == line); assert(choices && strlen(choices) > 0); while (1) { cinema_print_line(line, text); response = cinema_getch(); if (ABORT == response) break; if (strchr(choices, response)) break; cinema_print_line(2, "What? Try again!"); } return response; } int cinema_ynq_line (int line, char * prompt) { return cinema_interact_line(line, "ynqYNQ", prompt); } int cinema_getnum_line (int line, char * prompt) { int num; assert(0 == line || 1 == line); cinema_blank_line(line); cinema_print_line(line, prompt); num = (int)input_number(Cinema); return num; } int cinema_confirm (char * action_description) { char *msg; switch (random_range(4)) { case 0: msg = "Are you sure? [yn] "; break; case 1: msg = "Certain about that? [yn] "; break; case 2: msg = "Do you really mean it? [yn] "; break; default: msg = "Confirm that, would you? [yn] "; break; } return cinema_interact("ynqYNQ", action_description, msg, NULL); } int cinema_ynq (char *action_description) { return cinema_interact("ynqYNQ", action_description, NULL, NULL); } void cinema_scene (char *line1, char *line2, char *line3) { cinema_display(line1, line2, line3); morewait(); cinema_hide(); } int lastx= -1,lasty= -1; void drawplayer(void) { int c; if (E_COUNTRYSIDE == Current_Environment) { if (inbounds(lastx, lasty) && !offscreen(lastx, lasty)) { wmove(Levelw, screenmody(lasty), screenmodx(lastx)); c = Country[lastx][lasty].current_terrain_type; if (optionp(SHOW_COLOUR)) wattrset(Levelw, CHARATTR(c)); waddch(Levelw, c & 0xff); } wmove(Levelw, screenmody(Player.y), screenmodx(Player.x)); if (optionp(SHOW_COLOUR)) wattrset(Levelw, CHARATTR(PLAYER)); waddch(Levelw, PLAYER & 0xff); } else { if (inbounds(lastx, lasty) && !offscreen(lastx, lasty)) plotspot(lastx, lasty, (Player.status[BLINDED] > 0 ? FALSE : TRUE)); wmove(Levelw, screenmody(Player.y), screenmodx(Player.x)); if ((!Player.status[INVISIBLE]) || Player.status[TRUESIGHT]) { if (optionp(SHOW_COLOUR)) wattrset(Levelw, CHARATTR(PLAYER)); waddch(Levelw, PLAYER & 0xff); } } lastx = Player.x; lasty = Player.y; } void setlastxy(int new_x, int new_y) /* used when changing environments */ { lastx = new_x; lasty = new_y; } int litroom(int x, int y) { if (Level->site[x][y].roomnumber < ROOMBASE) return(FALSE); else return(loc_statusp(x,y,LIT) || Player.status[ILLUMINATION]); } void drawvision(int x, int y) { static int oldx = -1,oldy = -1; int i,j,c; if (Current_Environment != E_COUNTRYSIDE) { if (Player.status[BLINDED]) { drawspot(oldx,oldy); drawspot(x,y); drawplayer(); } else { if (Player.status[ILLUMINATION] > 0) { for (i= -2;i<3;i++) for (j= -2;j<3;j++) if (inbounds(x+i,y+j)) if (view_los_p(x+i,y+j,Player.x,Player.y)) dodrawspot(x+i,y+j); } else { for (i= -1;i<2;i++) for (j= -1;j<2;j++) if (inbounds(x+i,y+j)) dodrawspot(x+i,y+j); } drawplayer(); drawmonsters(FALSE); /* erase all monsters */ drawmonsters(TRUE); /* draw those now visible */ } if ((! gamestatusp(FAST_MOVE)) || (! optionp(JUMPMOVE))) omshowcursor(Player.x,Player.y); oldx = x; oldy = y; } else { for (i= -1;i<2;i++) for (j= -1;j<2;j++) if (inbounds(x+i,y+j)) { c_set(x+i, y+j, SEEN); if (!offscreen(x+i,y+j)) { wmove(Levelw,screenmody(y+j),screenmodx(x+i)); c = Country[x+i][y+j].current_terrain_type; if (optionp(SHOW_COLOUR)) wattrset(Levelw, CHARATTR(c)); waddch(Levelw,(c&0xff)); } } drawplayer(); omshowcursor(Player.x,Player.y); } } void omshowcursor(int x, int y) { if (! offscreen(x,y)) { wmove(Levelw,screenmody(y),screenmodx(x)); wrefresh(Levelw); } } void levelrefresh(void) { wrefresh(Levelw); } /* draws a particular spot under if in line-of-sight */ void drawspot(int x, int y) { Symbol c; if (inbounds(x,y)) { c = getspot(x,y,FALSE); if (c != Level->site[x][y].showchar) if (view_los_p(Player.x,Player.y,x,y)) { lset(x,y,SEEN); Level->site[x][y].showchar = c; putspot(x,y,c); } } } /* draws a particular spot regardless of line-of-sight */ void dodrawspot(int x, int y) { Symbol c; if (inbounds(x,y)) { c = getspot(x,y,FALSE); if (c != Level->site[x][y].showchar) { lset(x,y,SEEN); Level->site[x][y].showchar = c; putspot(x,y,c); } } } /* write a blank to a spot if it is floor */ void blankoutspot(int i, int j) { if (inbounds(i,j)) { lreset(i,j,LIT); lset(i, j, CHANGED); if (Level->site[i][j].locchar == FLOOR) { Level->site[i][j].showchar = SPACE; putspot(i,j,SPACE); } } } /* blank out a spot regardless */ void blotspot(int i, int j) { if (inbounds(i,j)) { lreset(i,j,SEEN); Level->site[i][j].showchar = SPACE; if (! offscreen(i,j)) { wmove(Levelw,screenmody(j),screenmodx(i)); wattrset(Levelw, CHARATTR(SPACE)); waddch(Levelw, SPACE&0xff); } } } /* for displaying activity specifically at some point */ void plotspot(int x, int y, int showmonster) { if (loc_statusp(x,y,SEEN)) putspot(x,y,getspot(x,y,showmonster)); else putspot(x,y,SPACE); } /* Puts c at x,y on screen. No fuss, no bother. */ void putspot(int x, int y, Symbol c) { if (! offscreen(x,y)) { wmove(Levelw,screenmody(y),screenmodx(x)); if (optionp(SHOW_COLOUR)) wattrset(Levelw, CHARATTR(c)); waddch(Levelw,(0xff&c)); } } /* regardless of line of sight, etc, draw a monster */ void plotmon(pmt m) { if (! offscreen(m->x,m->y)) { wmove(Levelw,screenmody(m->y),screenmodx(m->x)); if (optionp(SHOW_COLOUR)) wattrset(Levelw, CHARATTR(m->monchar)); waddch(Levelw,(m->monchar&0xff)); } } /* if display, displays monsters, otherwise erases them */ void drawmonsters(int display) { pml ml; for (ml=Level->mlist;ml!=NULL;ml=ml->next) { if (ml->m->hp > 0) { if (display) { if (view_los_p(Player.x,Player.y,ml->m->x,ml->m->y)) { if (Player.status[TRUESIGHT] || (! m_statusp(ml->m,M_INVISIBLE))) { if (!optionp(SHOW_COLOUR) && (ml->m->level > 5) && ((ml->m->monchar&0xff) != '@') && ((ml->m->monchar&0xff) != '|')) wstandout(Levelw); putspot(ml->m->x,ml->m->y,ml->m->monchar); if (!optionp(SHOW_COLOUR)) wstandend(Levelw); } } } else erase_monster(ml->m); } } } /* replace monster with what would be displayed if monster weren't there */ void erase_monster(pmt m) { if (loc_statusp(m->x,m->y,SEEN)) putspot(m->x,m->y,getspot(m->x,m->y,FALSE)); else blotspot(m->x,m->y); } /* find apt char to display at some location */ Symbol getspot(int x, int y, int showmonster) { #ifdef CENTER_ON_PLAYER /* funny scrolling may cause this. PGM */ if (!inbounds(x,y ) ) { return SPACE; } #endif if (loc_statusp(x,y,SECRET)) { if ( Level->site[x][y].roomnumber == RS_DRUID ) return(HEDGE); /* secret doors in druid temple are brambles -DAG */ else return(WALL); } else switch (Level->site[x][y].locchar) { case WATER: if (Level->site[x][y].creature == NULL) return(WATER); else if (m_statusp(Level->site[x][y].creature,SWIMMING)) return(WATER); else if (showmonster) return(Level->site[x][y].creature->monchar); else return(WATER); /* these sites never show anything but their location char's */ case CLOSED_DOOR: case LAVA: case FIRE: case ABYSS: return(Level->site[x][y].locchar); /* rubble and hedge don't show items on their location */ case RUBBLE: case HEDGE: if (showmonster && (Level->site[x][y].creature != NULL)) { if ((m_statusp(Level->site[x][y].creature,M_INVISIBLE)) && (! Player.status[TRUESIGHT])) return(getspot(x,y,FALSE)); else return (Level->site[x][y].creature->monchar); } else return(Level->site[x][y].locchar); /* everywhere else, first try to show monster, next show items, next show location char */ default: if (showmonster && (Level->site[x][y].creature != NULL)) { if ((m_statusp(Level->site[x][y].creature,M_INVISIBLE)) && (! Player.status[TRUESIGHT])) return(getspot(x,y,FALSE)); else return (Level->site[x][y].creature->monchar); } else if (Level->site[x][y].things != NULL) { if (Level->site[x][y].things->next != NULL) return(PILE); else return(Level->site[x][y].things->thing->objchar); } else return(Level->site[x][y].locchar); } } void commanderror(void) { erasemsg3(); wprintw(Msg3w, "%c : unknown command", Cmd); wrefresh(Msg3w); } void timeprint(void) { static char * old_month = 0; /* WSS * HACK * This shouldn't be here at all but time is so screwed up */ /* WSS * HACK * I don't know where else I can check for a new month reliably */ if (!old_month) old_month = month(); else { /* WSS * HACK * ptr comparision... works cause they're static */ if (old_month != month() && Player.rank[LEGION] > 0) { bank_account * account; account = bank_index_number(SalaryAccount); if (account) account->balance += SalaryAmount; old_month = month(); } } wclear(Timew); wprintw(Timew,"%d:%d",showhour(),showminute()); if (showminute()==0) waddch(Timew,'0'); wprintw(Timew,hour()>11 ? " PM \n" : " AM \n"); wprintw(Timew,month()); wprintw(Timew," the %d",day()); wprintw(Timew,ordinal(day())); wrefresh(Timew); } void comwinprint(void) { wclear(Comwin); wprintw(Comwin,"Hit: %d \n",Player.hit); wprintw(Comwin,"Dmg: %d \n",Player.dmg); wprintw(Comwin,"Def: %d \n",Player.defense); wprintw(Comwin,"Arm: %d \n",Player.absorption); wprintw(Comwin,"Spd: %d.%d \n", 5/Player.speed, 500/Player.speed%100); wrefresh(Comwin); } void dataprint(void) { wclear(Dataw); /* WDT HACK: I should make these fields spaced and appropriately justified. * Maybe I don't feel like it right now. */ wprintw(Dataw,"Hp:%d/%d Mana:%ld/%ld Au:%ld Level:%d/%ld Carry:%d/%d \n", Player.hp,Player.maxhp,Player.mana,Player.maxmana,Player.cash, Player.level,Player.xp,Player.itemweight,Player.maxweight); wprintw(Dataw,"Str:%d/%d Con:%d/%d Dex:%d/%d Agi:%d/%d Int:%d/%d Pow:%d/%d ", Player.str,Player.maxstr,Player.con,Player.maxcon, Player.dex,Player.maxdex,Player.agi,Player.maxagi, Player.iq,Player.maxiq,Player.pow,Player.maxpow); wrefresh(Dataw); } /* redraw everything currently displayed */ void redraw(void) { touchwin(curscr); wrefresh(curscr); } /* redraw each permanent window */ void xredraw(void) { touchwin(Msgw); touchwin(Msg3w); touchwin(Levelw); touchwin(Timew); touchwin(Flagw); touchwin(Dataw); touchwin(Locw); touchwin(Morew); touchwin(Phasew); touchwin(Comwin); wrefresh(Msgw); wrefresh(Msg3w); wrefresh(Levelw); wrefresh(Timew); wrefresh(Flagw); wrefresh(Dataw); wrefresh(Locw); wrefresh(Morew); wrefresh(Phasew); wrefresh(Comwin); } void menuaddch(char c) { waddch(Menuw,c); wrefresh(Menuw); } void morewait(void) { int display=TRUE; int c; if (gamestatusp(SUPPRESS_PRINTING)) return; do { wclear(Morew); if (display) wprintw(Morew,"*** MORE ***"); else wprintw(Morew,"+++ MORE +++"); display = ! display; wrefresh(Morew); /* c = wgetch(Msgw); */ c = wgetch(Morew); } while ((c != ' ') && (c != RETURN) && (c != EOF)); wclear(Morew); wrefresh(Morew); } int stillonblock(void) { int display=TRUE; int c; do { wclear(Morew); if (display) wprintw(Morew,"<<>>"); else wprintw(Morew,">>>STAY?<<<"); display = ! display; wrefresh(Morew); c = wgetch(Msgw); } while ((c != ' ') && (c != ESCAPE) && (c != EOF)); wclear(Morew); wrefresh(Morew); return (c == ' '); } void menuclear(void) { wclear(Menuw); touchwin(Menuw); wrefresh(Menuw); } void menuspellprint(int i) { int x,y; getyx(Menuw,y,x); if (y >= ScreenLength - 2) { wrefresh(Menuw); morewait(); wclear(Menuw); touchwin(Menuw); } wprintw(Menuw,spellid(i)); wprintw(Menuw,"(%d)\n",Spells[i].powerdrain); } void menuprint(char *s) { int x,y; getyx(Menuw,y,x); if (y >= ScreenLength - 2) { wrefresh(Menuw); morewait(); wclear(Menuw); touchwin(Menuw); } wprintw(Menuw,s); } void showmenu(void) { wrefresh(Menuw); } void endgraf(void) { clear(); touchwin(stdscr); refresh(); endwin(); } void plotchar(Symbol pyx, int x, int y) { if (! offscreen(x,y)) { wmove(Levelw,screenmody(y),screenmodx(x)); if (optionp(SHOW_COLOUR)) wattrset(Levelw, CHARATTR(pyx)); waddch(Levelw,(pyx&0xff)); wrefresh(Levelw); } } void draw_explosion(Symbol pyx, int x, int y) { int i,j; for(j=0;j<3;j++) { for(i=0;i<9;i++) plotchar(pyx,x+Dirs[0][i],y+Dirs[1][i]); usleep(150000); for(i=0;i<9;i++) plotchar(SPACE,x+Dirs[0][i],y+Dirs[1][i]); usleep(150000); } for(i=0;i<9;i++) plotspot(x+Dirs[0][i],y+Dirs[1][i],TRUE); wrefresh(Levelw); } char *msgscanstring(void) { static char instring[80],byte='x'; int i=0; instring[0]=0; byte = mgetc(); while (byte != '\n') { if ((byte == 8) || (byte == 127)) { /* ^h or delete */ if (i>0){ i--; dobackspace(); } instring[i] = 0; } else { instring[i] = byte; waddch(Msgw,byte); wrefresh(Msgw); i++; instring[i] = 0; } byte = mgetc(); } return(instring); } void locprint(char *s) { wclear(Locw); wprintw(Locw,s); wrefresh(Locw); } /* draw everything whether visible or not */ void drawscreen(void) { int i,j; if (Current_Environment == E_COUNTRYSIDE) for (i=0;ilevel_width;i++) for(j=0;jlevel_length;j++) lset(i,j,SEEN); if (Current_Environment == E_CITY) for (i = 0; i < NUMCITYSITES; i++) CitySiteList[i][0] = 1; show_screen(); } /*selects a number up to range */ /* WDT HACK! This should use the interaction code, and should allow * direct input. */ int getnumber(int range) { int done=FALSE,value=1; int atom; if (range==1) return(1); else while (! done) { clearmsg(); wprintw(Msg1w,"How many? Change with < or >, ESCAPE to select:"); mnumprint(value); #ifndef MSDOS do atom=mcigetc(); while ((atom != '<')&&(atom != '>')&&(atom!=ESCAPE)); if ((atom=='>') && (value < range)) value++; else if ((atom=='<') && (value > 1)) value--; else if (atom==ESCAPE) done = TRUE; #else atom=mcigetc(); switch (atom) { case '>': case 'k': #ifdef KEY_UP case KEY_UP: #endif if (value < range) value++; break; case '<': case 'j': #ifdef KEY_DOWN case KEY_DOWN: #endif if (value > 1) value--; break; #ifdef KEY_HOME case KEY_HOME: #endif value = 1; break; #ifdef KEY_LL case KEY_LL: #endif value = range; break; case ESCAPE: done = TRUE; break; } #endif } return(value); } static long input_number (WINDOW * w) { int ch; int ypos, xpos; int numlen = 0; int amount = 0; getyx(w, ypos, xpos); while (1) { ch = mvwgetch(w, ypos, xpos); if ('\n' == ch || '\r' == ch) { return amount; } else if (EOF == ch || ESCAPE == ch) { return ABORT; } else if (BACKSPACE == ch || DELETE == ch) { if (numlen > 0) { --numlen; amount /= 10; mvwaddch(w, ypos, --xpos, ' '); } } else if (isdigit(ch) && (numlen < 9)) { ++xpos; ++numlen; waddch(w, ch); amount = 10 * amount + (ch - '0'); } else { beep(); } } } /* reads a positive number up to 999999 */ /* WDT: now asks for the number, and receives it through the cinema * interface. Returns ABORT (-1) if aborted. */ long parsenum (char *message) { int number[8]; int place = -1; int i,x,y,mult=1; long num=0; char byte=' '; int entering_digits = TRUE; cinema_display(message, "enter a number or ESC: ", NULL); while (entering_digits) { byte = wgetch(Cinema); if ((byte == BACKSPACE) || (byte == DELETE)) { if (place > -1) { number[place] = 0; place--; getyx(Cinema,y,x); wmove(Cinema,y,x-1); waddch(Cinema,' '); wmove(Cinema,y,x-1); wrefresh(Cinema); } } else if ((byte <= '9') && (byte >= '0') && (place < 7)) { place++; number[place]=byte; waddch(Cinema,byte); wrefresh(Cinema); } else if (isprint(byte)) { /* I suppose I should beep here, to indicate that only digits belong. * Right now I'm just ignoring them. */ } else entering_digits = 0; } if (byte != '\n') num = ABORT; else { for (i=place;i>=0;i--) { num += mult*(number[i]-'0'); mult*=10; } } cinema_hide(); return num; } void maddch(char c) { waddch(Msgw,c); wrefresh(Msgw); } void display_death(char *source) { clear(); touchwin(stdscr); printw("\n\n\n\n"); printw("Requiescat In Pace, "); printw(Player.name); printw(" (%ld points)",calc_points()); strcpy(Str4,"Killed by "); strcat(Str4,source); printw("\n"); printw(Str4); printw("."); printw("\n\n\n\n\nHit 'c' to continue."); refresh(); while (wgetch(stdscr) != 'c') ; clear(); touchwin(stdscr); refresh(); extendlog(Str4,DEAD); } void display_win(void) { clear(); touchwin(stdscr); printw("\n\n\n\n"); printw(Player.name); if (Player.rank[ADEPT]) { printw(" is a total master of omega with %ld points!",FixedPoints); strcpy(Str4,"A total master of omega"); } else { strcpy(Str4,"retired a winner"); printw(" triumphed in omega with %ld points!",calc_points()); } printw("\n\n\n\n\nHit 'c' to continue."); refresh(); while (wgetch(stdscr) != 'c') ; clear(); touchwin(stdscr); refresh(); if (Player.rank[ADEPT]) extendlog(Str4,BIGWIN); else extendlog(Str4,WIN); } void display_quit(void) { clear(); touchwin(stdscr); printw("\n\n\n\n"); printw(Player.name); strcpy(Str4,"A quitter."); printw(" wimped out with %ld points!",calc_points()); printw("\n\n\n\n\nHit 'c' to continue."); refresh(); while (wgetch(stdscr) != 'c') ; clear(); touchwin(stdscr); refresh(); extendlog(Str4,QUIT); } void display_bigwin(void) { clear(); touchwin(stdscr); printw("\n\n\n\n"); printw(Player.name); strcpy(Str4,"retired, an Adept of Omega."); printw(" retired, an Adept of Omega with %ld points!",FixedPoints); printw("\n\n\n\n\nHit 'c' to continue."); refresh(); while (wgetch(stdscr) != 'c') ; clear(); touchwin(stdscr); refresh(); extendlog(Str4,BIGWIN); } void mnumprint(int n) { char numstr[20]; sprintf(numstr,"%d",n); bufferappend(numstr); wprintw(Msgw,"%d",n); wrefresh(Msgw); } void mlongprint(long n) { char numstr[20]; sprintf(numstr,"%ld",n); bufferappend(numstr); wprintw(Msgw,"%ld",n); wrefresh(Msgw); } void menunumprint(int n) { int x,y; getyx(Menuw,y,x); if (y >= ScreenLength - 2) { wrefresh(Menuw); morewait(); wclear(Menuw); touchwin(Menuw); } wprintw(Menuw,"%d",n); } void menulongprint(long n) { int x,y; getyx(Menuw,y,x); if (y >= ScreenLength - 2) { wrefresh(Menuw); morewait(); wclear(Menuw); touchwin(Menuw); } wprintw(Menuw,"%ld",n); } void dobackspace(void) { int x,y; getyx(Msgw,y,x); if (x > 0) { waddch(Msgw,' '); wmove(Msgw,y,x-1); waddch(Msgw,' '); wmove(Msgw,y,x-1); } wrefresh(Msgw); } void showflags(void) { phaseprint(); wclear(Flagw); if (Player.food < 0) wprintw(Flagw,"Starving\n"); else if (Player.food <= 3) wprintw(Flagw,"Weak\n"); else if (Player.food <= 10) wprintw(Flagw,"Ravenous\n"); else if (Player.food <= 20) wprintw(Flagw,"Hungry\n"); else if (Player.food <= 30) wprintw(Flagw,"A mite peckish\n"); else if (Player.food <= 36) wprintw(Flagw,"Content\n"); else if (Player.food <= 44) wprintw(Flagw,"Satiated\n"); else wprintw(Flagw,"Bloated\n"); if (Player.status[POISONED]>0) wprintw(Flagw,"Poisoned\n"); else wprintw(Flagw,"Vigorous\n"); if (Player.status[DISEASED]>0) wprintw(Flagw,"Diseased\n"); else wprintw(Flagw,"Healthy\n"); if (gamestatusp(MOUNTED)) wprintw(Flagw,"Mounted\n"); else if (Player.status[LEVITATING]) wprintw(Flagw,"Levitating\n"); else wprintw(Flagw,"Afoot\n"); wrefresh(Flagw); } void drawomega(void) { int i; clear(); touchwin(stdscr); for(i=0;i<7;i++) { move(1, 1); if (optionp(SHOW_COLOUR)) wattrset(stdscr, CHARATTR(CLR(LIGHT_BLUE))); printw("\n\n\n"); printw("\n *****"); printw("\n ****** ******"); printw("\n *** ***"); printw("\n *** ***"); printw("\n ** **"); printw("\n *** ***"); printw("\n ** **"); printw("\n ** **"); printw("\n *** ***"); printw("\n *** ***"); printw("\n ** **"); printw("\n * *** *** *"); printw("\n **** ****"); refresh(); usleep(200000); move(1, 1); if (optionp(SHOW_COLOUR)) wattrset(stdscr, CHARATTR(CLR(CYAN))); printw("\n\n\n"); printw("\n +++++"); printw("\n ++++++ ++++++"); printw("\n +++ +++"); printw("\n +++ +++"); printw("\n ++ ++"); printw("\n +++ +++"); printw("\n ++ ++"); printw("\n ++ ++"); printw("\n +++ +++"); printw("\n +++ +++"); printw("\n ++ ++"); printw("\n + +++ +++ +"); printw("\n ++++ ++++"); refresh(); usleep(200000); move(1, 1); if (optionp(SHOW_COLOUR)) wattrset(stdscr, CHARATTR(CLR(BLUE))); printw("\n\n\n"); printw("\n ....."); printw("\n ...... ......"); printw("\n ... ..."); printw("\n ... ..."); printw("\n .. .."); printw("\n ... ..."); printw("\n .. .."); printw("\n .. .."); printw("\n ... ..."); printw("\n ... ..."); printw("\n .. .."); printw("\n . ... ... ."); printw("\n .... ...."); refresh(); usleep(200000); } wattrset(stdscr, CHARATTR(CLR(WHITE))); } /* y is an absolute coordinate */ /* ScreenOffset is the upper left hand corner of the current screen in absolute coordinates */ #if 0 void screencheck(int y) { if (((y-ScreenOffset) < (ScreenLength/8)) || ((y-ScreenOffset) > (7*ScreenLength/8))) { ScreenOffset = y - (ScreenLength/2); show_screen(); if (Current_Environment != E_COUNTRYSIDE) drawmonsters(TRUE); if (!offscreen(Player.x,Player.y)) drawplayer(); } } #else void screencheck(int x, int y) { int change = 0; #ifdef CENTER_ON_PLAYER change = 1; ScreenOffset = y - (ScreenLength/2); ScreenXOffset = x - (ScreenWidth/2); #else #if 0 int width = 0; #endif if (((y-ScreenOffset) < (ScreenLength/8)) || ((y-ScreenOffset) > (7*ScreenLength/8))) { change = 1; ScreenOffset = y - (ScreenLength/2); } if (((x-ScreenXOffset) < (ScreenWidth/8)) || ((x-ScreenXOffset) > (7*ScreenWidth/8))) { #if 0 if ( Current_Environment == E_COUNTRYSIDE ) width = COUNTRY_WIDTH; else width = Level->level_width; /* PGM: this code prevents scrolling when near the right edge of the level, but this unfortunately results in a badly placed view when, for examples, restoring a save near the edge of a level. Ideas on fixing this, or moving it, appreciated. PGM July 1999. */ if ( ( (x-ScreenXOffset) + (7*ScreenWidth/8) ) < width +( ScreenWidth/8 ) ) #endif { change = 1; ScreenXOffset = x - (ScreenWidth/2); if (ScreenXOffset < 0) ScreenXOffset = 0; } } #endif if ( change == 1 ) { show_screen(); if (Current_Environment != E_COUNTRYSIDE) drawmonsters(TRUE); if (!offscreen(Player.x,Player.y)) drawplayer(); } } #endif void spreadroomlight(int x, int y, int roomno) { if (inbounds(x,y) && !loc_statusp(x,y,LIT) && Level->site[x][y].roomnumber == roomno) { lightspot(x,y); spreadroomlight(x+1,y,roomno); spreadroomlight(x,y+1,roomno); spreadroomlight(x-1,y,roomno); spreadroomlight(x,y-1,roomno); } } /* illuminate one spot at x y */ void lightspot(int x, int y) { Symbol c; lset(x,y,LIT); lset(x,y,SEEN); lset(x, y, CHANGED); c = getspot(x,y,FALSE); Level->site[x][y].showchar = c; putspot(x,y,c); } void spreadroomdark(int x, int y, int roomno) { if (inbounds(x,y)) if (loc_statusp(x,y,LIT) && (Level->site[x][y].roomnumber == roomno)) { blankoutspot(x,y); spreadroomdark(x+1,y,roomno); spreadroomdark(x,y+1,roomno); spreadroomdark(x-1,y,roomno); spreadroomdark(x,y-1,roomno); } } void display_pack(void) { int i; if (Player.packptr < 1) print3("Pack is empty."); else { menuclear(); menuprint("Items in Pack:\n"); for(i=0;iused) usechar = '>'; if (topline) W = Msg3w; else { W = Showline[slotnum]; hide_line(slotnum); } idchar = index_to_key(slotnum); touchwin(W); wclear(W); switch(slotnum) { case O_UP_IN_AIR: wprintw(W,"-- Object 'up in air':",usechar); break; case O_READY_HAND: wprintw(W,"-- %c%c ready hand: ",idchar,usechar); break; case O_WEAPON_HAND: wprintw(W,"-- %c%c weapon hand: ",idchar,usechar); break; case O_LEFT_SHOULDER: wprintw(W,"-- %c%c left shoulder: ",idchar,usechar); break; case O_RIGHT_SHOULDER: wprintw(W,"-- %c%c right shoulder: ",idchar,usechar); break; case O_BELT1: wprintw(W,"-- %c%c belt: ",idchar,usechar); break; case O_BELT2: wprintw(W,"-- %c%c belt: ",idchar,usechar); break; case O_BELT3: wprintw(W,"-- %c%c belt: ",idchar,usechar); break; case O_SHIELD: wprintw(W,"-- %c%c shield: ",idchar,usechar); break; case O_ARMOR: wprintw(W,"-- %c%c armor: ",idchar,usechar); break; case O_BOOTS: wprintw(W,"-- %c%c boots: ",idchar,usechar); break; case O_CLOAK: wprintw(W,"-- %c%c cloak: ",idchar,usechar); break; case O_RING1: wprintw(W,"-- %c%c finger: ",idchar,usechar); break; case O_RING2: wprintw(W,"-- %c%c finger: ",idchar,usechar); break; case O_RING3: wprintw(W,"-- %c%c finger: ",idchar,usechar); break; case O_RING4: wprintw(W,"-- %c%c finger: ",idchar,usechar); break; } if (Player.possessions[slotnum]== NULL) wprintw(W,"(slot vacant)"); else wprintw(W,itemid(Player.possessions[slotnum])); wrefresh(W); } int move_slot(int oldslot, int newslot, int maxslot) { if ((newslot >= 0) && (newslot < maxslot)){ wmove(Showline[oldslot],0,0); waddstr(Showline[oldslot],"--"); wrefresh(Showline[oldslot]); wmove(Showline[newslot],0,0); wstandout(Showline[newslot]); waddstr(Showline[newslot],">>"); wstandend(Showline[newslot]); wrefresh(Showline[newslot]); return(newslot); } else return(oldslot); } void colour_on(void) { } void colour_off(void) { wattrset(Levelw, CHARATTR(CLR(WHITE))); } void display_option_slot(int slot) { hide_line(slot); wclear(Showline[slot]); switch(slot) { case 1: wprintw(Showline[slot],"-- Option BELLICOSE [TF]: "); wprintw(Showline[slot], optionp(BELLICOSE) ? "(now T) " : "(now F) "); break; case 2: wprintw(Showline[slot],"-- Option JUMPMOVE [TF]: "); wprintw(Showline[slot], optionp(JUMPMOVE) ? "(now T) " : "(now F) "); break; case 3: wprintw(Showline[slot],"-- Option RUNSTOP [TF]: "); wprintw(Showline[slot], optionp(RUNSTOP) ? "(now T) " : "(now F) "); break; case 4: wprintw(Showline[slot],"-- Option PICKUP [TF]: "); wprintw(Showline[slot], optionp(PICKUP) ? "(now T) " : "(now F) "); break; case 5: wprintw(Showline[slot],"-- Option CONFIRM [TF]: "); wprintw(Showline[slot], optionp(CONFIRM) ? "(now T) " : "(now F) "); break; case 6: wprintw(Showline[slot],"-- Option TOPINV [TF]: "); wprintw(Showline[slot], optionp(TOPINV) ? "(now T) " : "(now F) "); break; case 7: wprintw(Showline[slot],"-- Option PACKADD [TF]: "); wprintw(Showline[slot], optionp(PACKADD) ? "(now T) " : "(now F) "); break; case 8: #ifdef COMPRESS_SAVE_FILES wprintw(Showline[slot],"-- Option COMPRESS [TF]: "); wprintw(Showline[slot], optionp(COMPRESS_OPTION) ? "(now T) " : "(now F) "); #endif break; case 9: wprintw(Showline[slot],"-- Option COLOUR [TF]: "); wprintw(Showline[slot], optionp(SHOW_COLOUR) ? "(now T) " : "(now F) "); break; case VERBOSITY_LEVEL: wprintw(Showline[slot], "-- Option VERBOSITY [(T)erse,(M)edium,(V)erbose]: (now "); if (Verbosity == VERBOSE) wprintw(Showline[slot],"Verbose)"); else if (Verbosity == MEDIUM) wprintw(Showline[slot],"Medium)"); else wprintw(Showline[slot],"Terse)"); break; case SEARCH_DURATION: wprintw(Showline[slot],"-- Option SEARCHNUM [0>x>10]: (now %d)",Searchnum); break; } wrefresh(Showline[slot]); } void display_stat_slot(int slot) { hide_line(slot); wclear(Showline[slot]); switch(slot) { case 1: wprintw(Showline[slot],"-- Strength ... [%d]: ", Player.str); break; case 2: wprintw(Showline[slot],"-- Constitution [%d]: ", Player.con); break; case 3: wprintw(Showline[slot],"-- Dexterity .. [%d]: ", Player.dex); break; case 4: wprintw(Showline[slot],"-- Agility .... [%d]: ", Player.agi); break; case 5: wprintw(Showline[slot],"-- Intelligence [%d]: ", Player.iq); break; case 6: wprintw(Showline[slot],"-- Power ...... [%d]: ", Player.pow); break; case 7: wprintw(Showline[slot],"-- HP ......... [%d]: ", Player.hp); break; case 8: wprintw(Showline[slot],"-- Max HP ..... [%d]: ", Player.maxhp); break; case 9: wprintw(Showline[slot],"-- Mana ....... [%d]: ", Player.mana); break; case 10: wprintw(Showline[slot],"-- Max Mana ... [%d]: ", Player.maxmana); break; case 11: wprintw(Showline[slot],"-- Cash ....... [%d]: ", Player.cash); break; } wrefresh(Showline[slot]); } void display_options(void) { int i; menuclear(); hide_line(0); for(i=1;i<=NUMOPTIONS;i++) display_option_slot(i); } void display_stats(void) { int i; menuclear(); hide_line(0); for(i=1;i<=NUMSTATS;i++) display_stat_slot(i); } /* nya ha ha ha ha haaaa.... */ void deathprint(void) { mgetc(); waddch(Msgw,'D'); wrefresh(Msgw); mgetc(); waddch(Msgw,'e'); wrefresh(Msgw); mgetc(); waddch(Msgw,'a'); wrefresh(Msgw); mgetc(); waddch(Msgw,'t'); wrefresh(Msgw); mgetc(); waddch(Msgw,'h'); wrefresh(Msgw); mgetc(); } void clear_if_necessary(void) { int x,y; getyx(Msg1w,y,x); if (x != 0) { wclear(Msg1w); wrefresh(Msg1w); } getyx(Msg2w,y,x); if (x != 0) { wclear(Msg2w); wrefresh(Msg2w); } getyx(Msg3w,y,x); if (x != 0) { erasemsg3(); wrefresh(Msg3w); } } int bufferpos = 0; void buffercycle(char *s) { strcpy(Stringbuffer[bufferpos++],s); if (bufferpos >= STRING_BUFFER_SIZE) bufferpos = 0; } int bufferappend(char *s) { int pos = bufferpos - 1; if (pos < 0) pos = STRING_BUFFER_SIZE - 1; if (strlen(Stringbuffer[pos]) + strlen(s) < 80 - 1) { strcat(Stringbuffer[pos],s); return 1; } else return 0; } void bufferprint(void) { int i = bufferpos - 1, c, finished = 0; clearmsg(); #ifndef MSDOS_SUPPORTED_ANTIQUE wprintw(Msg1w,"^p for previous message, ^n for next, anything else to quit."); #else wprintw(Msg1w,"^o for last message, ^n for next, anything else to quit."); #endif wrefresh(Msg1w); do { if (i >= STRING_BUFFER_SIZE) i = 0; if (i < 0) i = STRING_BUFFER_SIZE - 1; wclear(Msg2w); wprintw(Msg2w,Stringbuffer[i]); wrefresh(Msg2w); c = mgetc(); #ifndef MSDOS_SUPPORTED_ANTIQUE if (c == 16) /* ^p */ #else if (c == 15) /* ^o */ #endif i--; else if (c == 14) /* ^n */ i++; else finished = 1; } while (!finished); clearmsg(); omshowcursor(Player.x,Player.y); } void clear_screen(void) { clear(); touchwin(stdscr); refresh(); }