[BACK]Return to io.c CVS log [TXT][DIR] Up to [contributed] / early-roguelike / xrogue

Annotation of early-roguelike/xrogue/io.c, Revision 1.1.1.1

1.1       rubenllo    1: /*
                      2:     io.c - Various input/output functions
                      3:
                      4:     XRogue: Expeditions into the Dungeons of Doom
                      5:     Copyright (C) 1991 Robert Pietkivitch
                      6:     All rights reserved.
                      7:
                      8:     Based on "Advanced Rogue"
                      9:     Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
                     10:     All rights reserved.
                     11:
                     12:     Based on "Rogue: Exploring the Dungeons of Doom"
                     13:     Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
                     14:     All rights reserved.
                     15:
                     16:     See the file LICENSE.TXT for full copyright and licensing information.
                     17: */
                     18:
                     19: #include <curses.h>
                     20: #include <ctype.h>
                     21: #include <stdarg.h>
                     22: #include <string.h>
                     23: #include "rogue.h"
                     24:
                     25: void doadd(char *fmt, va_list ap);
                     26:
                     27: /*
                     28:  * msg:
                     29:  *      Display a message at the top of the screen.
                     30:  */
                     31:
                     32: static char msgbuf[BUFSIZ];
                     33: static int newpos = 0;
                     34:
                     35: /* VARARGS */
                     36: void
                     37: msg(char *fmt, ...)
                     38: {
                     39:     va_list ap;
                     40:     /*
                     41:      * if the string is "", just clear the line
                     42:      */
                     43:     if (*fmt == '\0')
                     44:     {
                     45:         wclear(msgw);
                     46:         overwrite(cw, msgw);
                     47:         wmove(msgw, 0, 0);
                     48:         clearok(msgw, FALSE);
                     49:         draw(msgw);
                     50:         mpos = 0;
                     51:         return;
                     52:     }
                     53:     /*
                     54:      * otherwise add to the message and flush it out
                     55:      */
                     56:     va_start(ap, fmt);
                     57:     doadd(fmt, ap);
                     58:     va_end(ap);
                     59:     endmsg();
                     60: }
                     61:
                     62: /*
                     63:  * add things to the current message
                     64:  */
                     65:
                     66: /* VARARGS */
                     67: void
                     68: addmsg(char *fmt, ...)
                     69: {
                     70:     va_list ap;
                     71:
                     72:     va_start(ap, fmt);
                     73:     doadd(fmt, ap);
                     74:     va_end(ap);
                     75: }
                     76:
                     77: /*
                     78:  * If there is no current message, do nothing.  Otherwise, prompt the
                     79:  * player with the --More-- string.  Then erase the message.
                     80:  */
                     81:
                     82: void
                     83: rmmsg(void)
                     84: {
                     85:     if (mpos) {
                     86:         wclear(msgw);
                     87:         overwrite(cw, msgw);
                     88:         mvwaddstr(msgw, 0, 0, huh);
                     89:         waddstr(msgw, morestr);
                     90:         clearok(msgw, FALSE);
                     91:         draw(msgw);
                     92:         wait_for(' ');
                     93:         msg("");
                     94:     }
                     95: }
                     96:
                     97: /*
                     98:  * Display a new msg (giving him a chance to see the previous one if it
                     99:  * is up there with the --More--)
                    100:  */
                    101:
                    102: void
                    103: endmsg(void)
                    104: {
                    105:     /* Needed to track where we are for 5.0 (PC) curses */
                    106:     register int x, y;
                    107:
                    108:     if (mpos) {
                    109:         /*
                    110:          * If this message will fit on the line (plus space for --More--)
                    111:          * then just add it (only during combat).
                    112:          */
                    113:         if (player.t_quiet < 0 && mpos + newpos + strlen(morestr) + 5 < cols) {
                    114:             wmove(msgw, 0, mpos + 5);
                    115:             newpos += mpos + 5;
                    116:             strcat(huh, "  ");
                    117:         }
                    118:         else {
                    119:             wclear(msgw);
                    120:             overwrite(cw, msgw);
                    121:             mvwaddstr(msgw, 0, 0, huh);
                    122:             waddstr(msgw, morestr);
                    123:             clearok(msgw, FALSE);
                    124:             draw(msgw);
                    125:             wait_for(' ');
                    126:             wclear(msgw);
                    127:             overwrite(cw, msgw);
                    128:             wmove(msgw, 0, 0);
                    129:             huh[0] = '\0';
                    130:         }
                    131:     }
                    132:     else {
                    133:         wclear(msgw);
                    134:         overwrite(cw, msgw);
                    135:         wmove(msgw, 0, 0);
                    136:         huh[0] = '\0';
                    137:     }
                    138:     strcat(huh, msgbuf);
                    139:     mvwaddstr(msgw, 0, 0, huh);
                    140:     getyx(msgw, y, x);
                    141:     mpos = newpos;
                    142:     newpos = 0;
                    143:     wmove(msgw, y, x);
                    144:     clearok(msgw, FALSE);
                    145:     draw(msgw);
                    146: }
                    147:
                    148: void
                    149: doadd(char *fmt, va_list ap)
                    150: {
                    151:     vsprintf((char *) &msgbuf[newpos], fmt, ap);
                    152:     newpos = strlen(msgbuf);
                    153: }
                    154:
                    155: /*
                    156:  * step_ok:
                    157:  *      returns true if it is ok for type to step on ch
                    158:  *      flgptr will be NULL if we don't know what the monster is yet!
                    159:  */
                    160:
                    161: bool
                    162: step_ok(int y, int x, int can_on_monst, struct thing *flgptr)
                    163: {
                    164:     /* can_on_monst = MONSTOK if all we care about are physical obstacles */
                    165:     register struct linked_list *item;
                    166:     register struct thing *tp;
                    167:     unsigned char ch;
                    168:
                    169:     /* What is here?  Don't check monster window if MONSTOK is set */
                    170:     if (can_on_monst == MONSTOK) ch = mvinch(y, x);
                    171:     else ch = winat(y, x);
                    172:
                    173:     if (can_on_monst == FIGHTOK && isalpha(ch) &&
                    174:         (item = find_mons(y, x)) != NULL) {
                    175:         tp = THINGPTR(item);    /* What monster is here? */
                    176:
                    177:         /* We can hit it if we're after it */
                    178:         if (flgptr->t_dest == &tp->t_pos) return TRUE;
                    179:
                    180:         /*
                    181:          * Otherwise, if we're friendly we'll hit it unless it is also
                    182:          * friendly or is our race.
                    183:          */
                    184:         if (off(*flgptr, ISFRIENDLY)    ||
                    185:             on(*tp, ISFRIENDLY)         ||
                    186:             flgptr->t_index == tp->t_index) return FALSE;
                    187:         else return TRUE;
                    188:     }
                    189:     else switch (ch)
                    190:     {
                    191:         case ' ':
                    192:         case VERTWALL:
                    193:         case HORZWALL:
                    194:         case SECRETDOOR:
                    195:             if (flgptr && on(*flgptr, CANINWALL)) return(TRUE);
                    196:             return FALSE;
                    197:         when SCROLL:
                    198:             if (can_on_monst == MONSTOK) {      /* Not a real obstacle */
                    199:                 move_free = 0;                  /* check free movement */
                    200:                 return(TRUE);
                    201:             }
                    202:             /*
                    203:              * If it is a scroll, it might be a scare monster scroll
                    204:              * so we need to look it up to see what type it is.
                    205:              */
                    206:             if (flgptr && flgptr->t_ctype == C_MONSTER) {
                    207:                 move_free = 1;
                    208:                 item = find_obj(y, x);
                    209:                 if (item != NULL &&
                    210:                     (OBJPTR(item))->o_which==S_SCARE &&
                    211:                     (flgptr == NULL || flgptr->t_stats.s_intel < 17)) {
                    212:                         move_free = 2;
                    213:                         return(FALSE); /* All but smart ones are scared */
                    214:                 }
                    215:             }
                    216:             return(TRUE);
                    217:         otherwise:
                    218:             return (!isalpha(ch));
                    219:     }
                    220:     /* return(FALSE); */
                    221:     /*NOTREACHED*/
                    222: }
                    223:
                    224: /*
                    225:  * shoot_ok:
                    226:  *      returns true if it is ok for type to shoot over ch
                    227:  */
                    228:
                    229: bool
                    230: shoot_ok(int ch)
                    231: {
                    232:     switch (ch)
                    233:     {
                    234:         case ' ':
                    235:         case VERTWALL:
                    236:         case HORZWALL:
                    237:         case SECRETDOOR:
                    238:         case FOREST:
                    239:             return FALSE;
                    240:         default:
                    241:             return (!isalpha(ch));
                    242:     }
                    243: }
                    244:
                    245: /*
                    246:  * status:
                    247:  *      Display the important stats line.  Keep the cursor where it was.
                    248:  * display: is TRUE, display unconditionally
                    249:  */
                    250:
                    251: void
                    252: status(bool display)
                    253: {
                    254:     register struct stats *stat_ptr, *max_ptr;
                    255:     register int oy = 0, ox = 0, temp;
                    256:     register char *pb;
                    257:     char buf[LINELEN];
                    258:     static int hpwidth = 0, s_hungry = -1;
                    259:     static int s_lvl = -1, s_hp = -1, s_str, maxs_str,
                    260:                 s_ac = 0;
                    261:     static short s_intel, s_dext, s_wisdom, s_const, s_charisma;
                    262:     static short maxs_intel, maxs_dext, maxs_wisdom, maxs_const, maxs_charisma;
                    263:     static unsigned long s_exp = 0;
                    264:     static int s_carry, s_pack;
                    265:     bool first_line=FALSE;
                    266:
                    267:     /* Go to English mode */
                    268:     nofont(cw);
                    269:
                    270:     stat_ptr = &pstats;
                    271:     max_ptr  = &max_stats;
                    272:
                    273:     /*
                    274:      * If nothing has changed in the first line, then skip it
                    275:      */
                    276:     if (!display                                &&
                    277:         s_lvl == level                          &&
                    278:         s_intel == stat_ptr->s_intel            &&
                    279:         s_wisdom == stat_ptr->s_wisdom          &&
                    280:         s_dext == dex_compute()                 &&
                    281:         s_const == stat_ptr->s_const            &&
                    282:         s_charisma == stat_ptr->s_charisma      &&
                    283:         s_str == str_compute()                  &&
                    284:         s_hungry == hungry_state                &&
                    285:         maxs_intel == max_ptr->s_intel          &&
                    286:         maxs_wisdom == max_ptr->s_wisdom        &&
                    287:         maxs_dext == max_ptr->s_dext            &&
                    288:         maxs_const == max_ptr->s_const          &&
                    289:         maxs_charisma == max_ptr->s_charisma    &&
                    290:         maxs_str == max_ptr->s_str              ) goto line_two;
                    291:
                    292:     /* Display the first line */
                    293:     first_line = TRUE;
                    294:     getyx(cw, oy, ox);
                    295:     sprintf(buf, "Int:%d(%d)  Str:%d", stat_ptr->s_intel,
                    296:         max_ptr->s_intel, str_compute());
                    297:
                    298:     /* Maximum strength */
                    299:     pb = &buf[strlen(buf)];
                    300:     sprintf(pb, "(%d)", max_ptr->s_str);
                    301:
                    302:     pb = &buf[strlen(buf)];
                    303:     sprintf(pb, "  Wis:%d(%d)  Dxt:%d(%d)  Con:%d(%d)  Cha:%d(%d)",
                    304:         stat_ptr->s_wisdom,max_ptr->s_wisdom,dex_compute(),max_ptr->s_dext,
                    305:         stat_ptr->s_const,max_ptr->s_const,stat_ptr->s_charisma,
                    306:         max_ptr->s_charisma);
                    307:
                    308:     /* Update first line status */
                    309:     s_intel = stat_ptr->s_intel;
                    310:     s_wisdom = stat_ptr->s_wisdom;
                    311:     s_dext = dex_compute();
                    312:     s_const = stat_ptr->s_const;
                    313:     s_charisma = stat_ptr->s_charisma;
                    314:     s_str = str_compute();
                    315:     maxs_intel = max_ptr->s_intel;
                    316:     maxs_wisdom = max_ptr->s_wisdom;
                    317:     maxs_dext = max_ptr->s_dext;
                    318:     maxs_const = max_ptr->s_const;
                    319:     maxs_charisma = max_ptr->s_charisma;
                    320:     maxs_str = max_ptr->s_str;
                    321:
                    322:     /* Print the line */
                    323:     mvwaddstr(cw, lines-2, 0, buf);
                    324:     switch (hungry_state) {
                    325:         case F_SATIATED:
                    326:             waddstr(cw, "  Satiated");
                    327:         when F_OKAY: ;
                    328:         when F_HUNGRY:
                    329:             waddstr(cw, "  Hungry");
                    330:         when F_WEAK:
                    331:             waddstr(cw, "  Weak");
                    332:         when F_FAINT:
                    333:             waddstr(cw, "  Fainting");
                    334:     }
                    335:     wclrtoeol(cw);
                    336:     s_hungry = hungry_state;
                    337:
                    338:     /*
                    339:      * If nothing has changed since the last status, don't
                    340:      * bother.
                    341:      */
                    342: line_two:
                    343:     if (!display                                        &&
                    344:         s_lvl == level                                  &&
                    345:         s_hp == stat_ptr->s_hpt                         &&
                    346:         s_ac == ac_compute(FALSE) - dext_prot(s_dext)   &&
                    347:         s_pack == stat_ptr->s_pack                      &&
                    348:         s_carry == stat_ptr->s_carry                    &&
                    349:         s_exp == stat_ptr->s_exp                        ) {
                    350:         newfont(cw);
                    351:         return;
                    352:     }
                    353:
                    354:     if (!first_line) getyx(cw, oy, ox);
                    355:     if (s_hp != max_ptr->s_hpt) {
                    356:         temp = s_hp = max_ptr->s_hpt;
                    357:         for (hpwidth = 0; temp; hpwidth++)
                    358:             temp /= 10;
                    359:     }
                    360:     sprintf(buf, "Lvl:%d  Hp:%*d(%*d)  Ac:%d  Carry:%d(%d)  Exp:%d/%lu  %s",
                    361:         level, hpwidth, stat_ptr->s_hpt, hpwidth, max_ptr->s_hpt,
                    362:         ac_compute(FALSE) - dext_prot(s_dext),stat_ptr->s_pack/10,
                    363:         stat_ptr->s_carry/10, stat_ptr->s_lvl, stat_ptr->s_exp,
                    364:         cnames[player.t_ctype][min(stat_ptr->s_lvl-1, NUM_CNAMES-1)]);
                    365:
                    366:     /*
                    367:      * Save old status
                    368:      */
                    369:     s_lvl = level;
                    370:     s_hp = stat_ptr->s_hpt;
                    371:     s_ac = ac_compute(FALSE) - dext_prot(s_dext);
                    372:     s_pack = stat_ptr->s_pack;
                    373:     s_carry = stat_ptr->s_carry;
                    374:     s_exp = stat_ptr->s_exp;
                    375:     mvwaddstr(cw, lines-1, 0, buf);
                    376:     wclrtoeol(cw);
                    377:     newfont(cw);
                    378:     wmove(cw, oy, ox);
                    379: }
                    380:
                    381: /*
                    382:  * wait_for
                    383:  *      Sit around until the guy types the right key
                    384:  */
                    385:
                    386: void
                    387: wait_for(char ch)
                    388: {
                    389:     register char c;
                    390:
                    391:     clearok(msgw, FALSE);
                    392:     if (ch == '\n') {
                    393:         while ((c = wgetch(msgw)) != '\n' && c != '\r') {
                    394:             continue;
                    395:         }
                    396:     }
                    397:     else {
                    398:         while (wgetch(msgw) != ch) {
                    399:             continue;
                    400:         }
                    401:     }
                    402: }
                    403:
                    404:
                    405: /*
                    406:  * over_win:
                    407:  *      Given a current window, a new window, and the max y and x of the
                    408:  *      new window, paint the new window on top of the old window without
                    409:  *      destroying any of the old window.  Current window and new window
                    410:  *      are assumed to have lines lines and cols columns (max y and max x
                    411:  *      pertain only the the useful information to be displayed.
                    412:  *      If redraw is non-zero, we wait for the character "redraw" to be
                    413:  *      typed and then redraw the starting screen.
                    414:  */
                    415:
                    416: void
                    417: over_win(WINDOW *oldwin, WINDOW *newin, int maxy, int maxx, int cursory,
                    418:          int cursorx, char redraw)
                    419: {
                    420:     char blanks[LINELEN+1];
                    421:     register int line, i;
                    422:     WINDOW *ow; /* Overlay window */
                    423:
                    424:     /* Create a blanking line */
                    425:     for (i=0; i<maxx && i<cols && i<LINELEN; i++) blanks[i] = ' ';
                    426:     blanks[i] = '\0';
                    427:
                    428:     /* Create the window we will display */
                    429:     ow = newwin(lines, cols, 0, 0);
                    430:
                    431:     /* Blank out the area we want to use */
                    432:     if (oldwin == cw) {
                    433:         msg("");
                    434:         line = 1;
                    435:     }
                    436:     else line = 0;
                    437:
                    438:     overwrite(oldwin, ow);      /* Get a copy of the old window */
                    439:
                    440:     /* Do the remaining blanking */
                    441:     for (; line < maxy; line++) mvwaddstr(ow, line, 0, blanks);
                    442:
                    443:     overlay(newin, ow); /* Overlay our new window */
                    444:
                    445:     /* Move the cursor to the specified location */
                    446:     wmove(ow, cursory, cursorx);
                    447:
                    448:     clearok(ow, FALSE);         /* Draw inventory without clearing */
                    449:     draw(ow);
                    450:
                    451:     if (redraw) {
                    452:         wait_for(redraw);
                    453:
                    454:         clearok(oldwin, FALSE);         /* Setup to redraw current screen */
                    455:         touchwin(oldwin);               /* clearing first */
                    456:         draw(oldwin);
                    457:     }
                    458:
                    459:     delwin(ow);
                    460: }
                    461:
                    462:
                    463: /*
                    464:  * show_win:
                    465:  *      function used to display a window and wait before returning
                    466:  */
                    467:
                    468: void
                    469: show_win(WINDOW *scr, char *message)
                    470: {
                    471:     mvwaddstr(scr, 0, 0, message);
                    472:     touchwin(scr);
                    473:     wmove(scr, hero.y, hero.x);
                    474:     draw(scr);
                    475:     wait_for(' ');
                    476:     restscr(cw);
                    477: }
                    478:
                    479: /*
                    480:  * dbotline:
                    481:  *      Displays message on bottom line and waits for a space to return
                    482:  */
                    483:
                    484: void
                    485: dbotline(WINDOW *scr, char *message)
                    486: {
                    487:         mvwaddstr(scr,lines-1,0,message);
                    488:         draw(scr);
                    489:         wait_for(' ');
                    490: }
                    491:
                    492: /*
                    493:  * restscr:
                    494:  *      Restores the screen to the terminal
                    495:  */
                    496:
                    497: void
                    498: restscr(WINDOW *scr)
                    499: {
                    500:         clearok(scr,TRUE);
                    501:         touchwin(scr);
                    502:         draw(scr);
                    503: }
                    504:
                    505: /*
                    506:  * netread:
                    507:  *      Read a byte, short, or long machine independently
                    508:  *      Always returns the value as an unsigned long.
                    509:  */
                    510:
                    511: unsigned long
                    512: netread(int *error, int size, FILE *stream)
                    513: {
                    514:     unsigned long result = 0L,  /* What we read in */
                    515:                   partial;      /* Partial value */
                    516:     int nextc,  /* The next byte */
                    517:         i;      /* To index through the result a byte at a time */
                    518:
                    519:     /* Be sure we have a right sized chunk */
                    520:     if (size < 1 || size > 4) {
                    521:         *error = 1;
                    522:         return(0L);
                    523:     }
                    524:
                    525:     for (i=0; i<size; i++) {
                    526:         nextc = getc(stream);
                    527:         if (nextc == EOF) {
                    528:             *error = 1;
                    529:             return(0L);
                    530:         }
                    531:         else {
                    532:             partial = (unsigned long) (nextc & 0xff);
                    533:             partial <<= 8*i;
                    534:             result |= partial;
                    535:         }
                    536:     }
                    537:
                    538:     *error = 0;
                    539:     return(result);
                    540: }
                    541:
                    542: /*
                    543:  * netwrite:
                    544:  *      Write out a byte, short, or long machine independently.
                    545:  * value: What to write
                    546:  * size: How much to write out
                    547:  * stream: Where to write it
                    548:  */
                    549:
                    550: int
                    551: netwrite(unsigned long value, int size, FILE *stream)
                    552: {
                    553:     int i;      /* Goes through value one byte at a time */
                    554:     char outc;  /* The next character to be written */
                    555:
                    556:     /* Be sure we have a right sized chunk */
                    557:     if (size < 1 || size > 4) return(0);
                    558:
                    559:     for (i=0; i<size; i++) {
                    560:         outc = (char) ((value >> (8 * i)) & 0xff);
                    561:         putc(outc, stream);
                    562:     }
                    563:     return(size);
                    564: }
                    565:

CVSweb