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

Annotation of early-roguelike/arogue5/util.c, Revision 1.1.1.1

1.1       rubenllo    1: /*
                      2:  * all sorts of miscellaneous routines
                      3:  *
                      4:  * Advanced Rogue
                      5:  * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
                      6:  * All rights reserved.
                      7:  *
                      8:  * Based on "Rogue: Exploring the Dungeons of Doom"
                      9:  * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
                     10:  * All rights reserved.
                     11:  *
                     12:  * See the file LICENSE.TXT for full copyright and licensing information.
                     13:  */
                     14:
                     15: #include "curses.h"
                     16: #include "rogue.h"
                     17: #include <ctype.h>
                     18: #include <string.h>
                     19:
                     20: /*
                     21:  * aggravate:
                     22:  *     aggravate all the monsters on this level
                     23:  */
                     24:
                     25: void
                     26: aggravate(void)
                     27: {
                     28:     register struct linked_list *mi;
                     29:
                     30:     for (mi = mlist; mi != NULL; mi = next(mi))
                     31:        runto(THINGPTR(mi), &hero);
                     32: }
                     33: 
                     34: /*
                     35:  * cansee:
                     36:  *     returns true if the hero can see a certain coordinate.
                     37:  */
                     38:
                     39: bool
                     40: cansee(int y, int x)
                     41: {
                     42:     register struct room *rer;
                     43:     register int radius;
                     44:     coord tp;
                     45:
                     46:     if (on(player, ISBLIND))
                     47:        return FALSE;
                     48:
                     49:     tp.y = y;
                     50:     tp.x = x;
                     51:     rer = roomin(&tp);
                     52:
                     53:     /* How far can we see? */
                     54:     if (levtype == OUTSIDE) {
                     55:        if (daytime) radius = 36;
                     56:        else if (lit_room(rer)) radius = 9;
                     57:        else radius = 3;
                     58:     }
                     59:     else radius = 3;
                     60:
                     61:     /*
                     62:      * We can only see if the hero in the same room as
                     63:      * the coordinate and the room is lit or if it is close.
                     64:      */
                     65:     return ((rer != NULL &&
                     66:             levtype != OUTSIDE &&
                     67:             (levtype != MAZELEV ||     /* Maze level needs direct line */
                     68:              maze_view(tp.y, tp.x)) &&
                     69:             rer == roomin(&hero) &&
                     70:             lit_room(rer)) ||
                     71:            DISTANCE(y, x, hero.y, hero.x) < radius);
                     72: }
                     73: 
                     74: /*
                     75:  * check_level:
                     76:  *     Check to see if the guy has gone up a level.
                     77:  *
                     78:  *     Return points needed to obtain next level.
                     79:  *
                     80:  * These are the beginning experience levels for all players.
                     81:  * All further experience levels are computed by muliplying by 2
                     82:  * up through MAXDOUBLE.
                     83:  */
                     84: #define MAXDOUBLE 14   /* Maximum number of times score is doubled */
                     85: static struct {
                     86:     long base; /* What it starts out at for doubling */
                     87:     long cap;  /* The maximum before doubling stops */
                     88: } e_levels[4] = {
                     89:        /* You must change MAXDOUBLE if you change the cap figure */
                     90:        { 90L,  1474560L },     /* Fighter */
                     91:        { 130L, 2129920L },     /* Magician */
                     92:        { 110L, 1802240L },     /* cleric */
                     93:        { 75L,  1228800L }      /* Thief */
                     94: };
                     95:
                     96: long
                     97: check_level(bool get_spells)
                     98: {
                     99:     register int i, j, add = 0;
                    100:     register unsigned long exp;
                    101:     long retval;       /* Return value */
                    102:     int nsides = 0;
                    103:
                    104:     /* See if we are past the doubling stage */
                    105:     exp = e_levels[player.t_ctype].cap;
                    106:     if (pstats.s_exp >= exp) {
                    107:        i = pstats.s_exp/exp;   /* First get amount above doubling area */
                    108:        retval = exp + i * exp; /* Compute next higher boundary */
                    109:        i += MAXDOUBLE; /* Add in the previous doubled levels */
                    110:     }
                    111:     else {
                    112:        i = 0;
                    113:        exp = e_levels[player.t_ctype].base;
                    114:        while (exp <= pstats.s_exp) {
                    115:            i++;
                    116:            exp <<= 1;
                    117:        }
                    118:        retval = exp;
                    119:     }
                    120:     if (++i > pstats.s_lvl) {
                    121:        switch (player.t_ctype) {
                    122:            case C_FIGHTER:     nsides = 10;
                    123:            when C_MAGICIAN:    nsides = 4;
                    124:            when C_CLERIC:      nsides = 8;
                    125:            when C_THIEF:       nsides = 6;
                    126:        }
                    127:
                    128:        /* Take care of multi-level jumps */
                    129:        for (j=0; j < (i-pstats.s_lvl); j++)
                    130:            add += max(1, roll(1,nsides) + const_bonus());
                    131:        max_stats.s_hpt += add;
                    132:        if ((pstats.s_hpt += add) > max_stats.s_hpt)
                    133:            pstats.s_hpt = max_stats.s_hpt;
                    134:        sprintf(outstring,"Welcome, %s, to level %d",
                    135:            cnames[player.t_ctype][min(i-1, 10)], i);
                    136:        msg(outstring);
                    137:        if (get_spells) {
                    138:            pray_time = 0;      /* A new round of prayers */
                    139:            spell_power = 0; /* A new round of spells */
                    140:        }
                    141:     }
                    142:     pstats.s_lvl = i;
                    143:     return(retval);
                    144: }
                    145: 
                    146: /*
                    147:  * Used to modify the playes strength
                    148:  * it keeps track of the highest it has been, just in case
                    149:  */
                    150:
                    151: void
                    152: chg_str(int amt)
                    153: {
                    154:     register int ring_str;             /* ring strengths */
                    155:     register struct stats *ptr;                /* for speed */
                    156:
                    157:     ptr = &pstats;
                    158:     ring_str = ring_value(R_ADDSTR);
                    159:     ptr->s_str -= ring_str;
                    160:     ptr->s_str += amt;
                    161:     if (ptr->s_str > 25)
                    162:        ptr->s_str = 25;
                    163:     if (ptr->s_str > max_stats.s_str)
                    164:        max_stats.s_str = ptr->s_str;
                    165:     ptr->s_str += ring_str;
                    166:     if (ptr->s_str <= 0)
                    167:        death(D_STRENGTH);
                    168:     updpack(TRUE);
                    169: }
                    170: 
                    171: /*
                    172:  * this routine computes the players current AC without dex bonus's
                    173:  */
                    174: int
                    175: ac_compute(void)
                    176: {
                    177:     register int ac;
                    178:
                    179:     ac  = cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm;
                    180:     ac -= ring_value(R_PROTECT);
                    181:     if (cur_misc[WEAR_BRACERS] != NULL)
                    182:        ac -= cur_misc[WEAR_BRACERS]->o_ac;
                    183:     if (cur_misc[WEAR_CLOAK] != NULL)
                    184:        ac -= cur_misc[WEAR_CLOAK]->o_ac;
                    185:
                    186:     /* If player has the cloak, must be wearing it */
                    187:     if (cur_relic[EMORI_CLOAK]) ac -= 5;
                    188:
                    189:     if (ac > 10)
                    190:        ac = 10;
                    191:     return(ac);
                    192: }
                    193:
                    194: /*
                    195:  * this routine computes the players current strength
                    196:  */
                    197: int
                    198: str_compute(void)
                    199: {
                    200:     if (cur_misc[WEAR_GAUNTLET] != NULL                &&
                    201:        cur_misc[WEAR_GAUNTLET]->o_which == MM_G_OGRE) {
                    202:        if (cur_misc[WEAR_GAUNTLET]->o_flags & ISCURSED)
                    203:            return (3);
                    204:        else
                    205:            return (18);
                    206:     }
                    207:     else
                    208:            return (pstats.s_str);
                    209: }
                    210:
                    211: /*
                    212:  * this routine computes the players current dexterity
                    213:  */
                    214: int
                    215: dex_compute(void)
                    216: {
                    217:     if (cur_misc[WEAR_GAUNTLET] != NULL                &&
                    218:        cur_misc[WEAR_GAUNTLET]->o_which == MM_G_DEXTERITY) {
                    219:        if (cur_misc[WEAR_GAUNTLET]->o_flags & ISCURSED)
                    220:            return (3);
                    221:        else
                    222:            return (18);
                    223:     }
                    224:     else
                    225:            return (pstats.s_dext);
                    226: }
                    227:
                    228: 
                    229: /*
                    230:  * diag_ok:
                    231:  *     Check to see if the move is legal if it is diagonal
                    232:  */
                    233:
                    234: bool
                    235: diag_ok(coord *sp, coord *ep, struct thing *flgptr)
                    236: {
                    237:     register int numpaths = 0;
                    238:
                    239:     /* Horizontal and vertical moves are always ok */
                    240:     if (ep->x == sp->x || ep->y == sp->y)
                    241:        return TRUE;
                    242:
                    243:     /* Diagonal moves are not allowed if there is a horizontal or
                    244:      * vertical path to the destination
                    245:      */
                    246:     if (step_ok(ep->y, sp->x, MONSTOK, flgptr)) numpaths++;
                    247:     if (step_ok(sp->y, ep->x, MONSTOK, flgptr)) numpaths++;
                    248:     return(numpaths != 1);
                    249: }
                    250: 
                    251: /*
                    252:  * eat:
                    253:  *     He wants to eat something, so let him try
                    254:  */
                    255:
                    256: void
                    257: eat(void)
                    258: {
                    259:     register struct linked_list *item;
                    260:
                    261:     if ((item = get_item(pack, "eat", FOOD)) == NULL)
                    262:        return;
                    263:     if ((OBJPTR(item))->o_which == 1)
                    264:        msg("My, that was a yummy %s", fruit);
                    265:     else {
                    266:        if (rnd(100) > 70) {
                    267:            msg("Yuk, this food tastes awful");
                    268:
                    269:            /* Do a check for overflow before increasing experience */
                    270:            if (pstats.s_exp + 1L > pstats.s_exp) pstats.s_exp++;
                    271:            check_level(TRUE);
                    272:        }
                    273:        else
                    274:            msg("Yum, that tasted good");
                    275:     }
                    276:     if ((food_left += HUNGERTIME + rnd(400) - 200) > STOMACHSIZE)
                    277:        food_left = STOMACHSIZE;
                    278:     del_pack(item);
                    279:     hungry_state = F_OKAY;
                    280:     updpack(TRUE);
                    281: }
                    282: 
                    283: /*
                    284:  * pick a random position around the give (y, x) coordinates
                    285:  */
                    286: coord *
                    287: fallpos(coord *pos, bool be_clear, int range)
                    288: {
                    289:        register int tried, i, j;
                    290:        register char ch;
                    291:        static coord ret;
                    292:        static short masks[] = {
                    293:                0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100 };
                    294:
                    295: /*
                    296:  * Pick a spot at random centered on the position given by 'pos' and
                    297:  * up to 'range' squares away from 'pos'
                    298:  *
                    299:  * If 'be_clear' is TRUE, the spot must be either FLOOR or PASSAGE
                    300:  * inorder to be considered valid
                    301:  *
                    302:  *
                    303:  * Generate a number from 0 to 8, representing the position to pick.
                    304:  * Note that this DOES include the positon 'pos' itself
                    305:  *
                    306:  * If this position is not valid, mark it as 'tried', and pick another.
                    307:  * Whenever a position is picked that has been tried before,
                    308:  * sequentially find the next untried position. This eliminates costly
                    309:  * random number generation
                    310:  */
                    311:
                    312:        tried = 0;
                    313:        while( tried != 0x1ff ) {
                    314:                i = rnd(9);
                    315:                while( tried & masks[i] )
                    316:                        i = (i + 1) % 9;
                    317:
                    318:                tried |= masks[i];
                    319:
                    320:                for( j = 1; j <= range; j++ ) {
                    321:                        ret.x = pos->x + j*grid[i].x;
                    322:                        ret.y = pos->y + j*grid[i].y;
                    323:
                    324:                        if (ret.x == hero.x && ret.y == hero.y)
                    325:                                continue; /* skip the hero */
                    326:
                    327:                        if (ret.x < 0 || ret.x > COLS - 1 ||
                    328:                            ret.y < 1 || ret.y > LINES - 3)
                    329:                                continue; /* off the screen? */
                    330:
                    331:                        ch = CCHAR( winat(ret.y, ret.x) );
                    332:
                    333:                        /*
                    334:                         * Check to make certain the spot is valid
                    335:                         */
                    336:                        switch( ch ) {
                    337:                        case FLOOR:
                    338:                        case PASSAGE:
                    339:                                return( &ret );
                    340:                        case GOLD:
                    341:                        case SCROLL:
                    342:                        case POTION:
                    343:                        case STICK:
                    344:                        case RING:
                    345:                        case WEAPON:
                    346:                        case ARMOR:
                    347:                        case MM:
                    348:                        case FOOD:
                    349:                                if(!be_clear && levtype != POSTLEV)
                    350:                                        return( &ret );
                    351:                        default:
                    352:                                break;
                    353:                        }
                    354:                }
                    355:        }
                    356:        return( NULL );
                    357: }
                    358:
                    359: 
                    360: /*
                    361:  * find_mons:
                    362:  *     Find the monster from his corrdinates
                    363:  */
                    364:
                    365: struct linked_list *
                    366: find_mons(int y, int x)
                    367: {
                    368:     register struct linked_list *item;
                    369:     register struct thing *th;
                    370:
                    371:     for (item = mlist; item != NULL; item = next(item))
                    372:     {
                    373:        th = THINGPTR(item);
                    374:        if (th->t_pos.y == y && th->t_pos.x == x)
                    375:            return item;
                    376:     }
                    377:     return NULL;
                    378: }
                    379: 
                    380: /*
                    381:  * find_obj:
                    382:  *     find the unclaimed object at y, x
                    383:  */
                    384:
                    385: struct linked_list *
                    386: find_obj(int y, int x)
                    387: {
                    388:     register struct linked_list *obj;
                    389:     register struct object *op;
                    390:
                    391:     for (obj = lvl_obj; obj != NULL; obj = next(obj))
                    392:     {
                    393:        op = OBJPTR(obj);
                    394:        if (op->o_pos.y == y && op->o_pos.x == x)
                    395:                return obj;
                    396:     }
                    397:     return NULL;
                    398: }
                    399:
                    400: 
                    401: /*
                    402:  * set up the direction co_ordinate for use in varios "prefix" commands
                    403:  */
                    404: bool
                    405: get_dir(void)
                    406: {
                    407:     register char *prompt;
                    408:     register bool gotit;
                    409:
                    410:     prompt = terse ? "Direction?" :  "Which direction? ";
                    411:     msg(prompt);
                    412:     do
                    413:     {
                    414:        gotit = TRUE;
                    415:        switch (readchar())
                    416:        {
                    417:            case 'h': case'H': delta.y =  0; delta.x = -1;
                    418:            when 'j': case'J': delta.y =  1; delta.x =  0;
                    419:            when 'k': case'K': delta.y = -1; delta.x =  0;
                    420:            when 'l': case'L': delta.y =  0; delta.x =  1;
                    421:            when 'y': case'Y': delta.y = -1; delta.x = -1;
                    422:            when 'u': case'U': delta.y = -1; delta.x =  1;
                    423:            when 'b': case'B': delta.y =  1; delta.x = -1;
                    424:            when 'n': case'N': delta.y =  1; delta.x =  1;
                    425:            when ESCAPE: return FALSE;
                    426:            otherwise:
                    427:                mpos = 0;
                    428:                msg(prompt);
                    429:                gotit = FALSE;
                    430:        }
                    431:     } until (gotit);
                    432:     if ((on(player, ISHUH) || on(player, ISDANCE)) && rnd(100) > 20) {
                    433:        do
                    434:        {
                    435:            delta = grid[rnd(9)];
                    436:        } while (delta.y == 0 && delta.x == 0);
                    437:     }
                    438:     mpos = 0;
                    439:     return TRUE;
                    440: }
                    441: 
                    442: /*
                    443:  * see if the object is one of the currently used items
                    444:  */
                    445: bool
                    446: is_current(struct object *obj)
                    447: {
                    448:     if (obj == NULL)
                    449:        return FALSE;
                    450:     if (obj == cur_armor               || obj == cur_weapon            ||
                    451:        obj == cur_ring[LEFT_1]         || obj == cur_ring[LEFT_2]      ||
                    452:        obj == cur_ring[LEFT_3]         || obj == cur_ring[LEFT_4]      ||
                    453:        obj == cur_ring[RIGHT_1]        || obj == cur_ring[RIGHT_2]     ||
                    454:        obj == cur_ring[RIGHT_3]        || obj == cur_ring[RIGHT_4]     ||
                    455:        obj == cur_misc[WEAR_BOOTS]     || obj == cur_misc[WEAR_JEWEL]  ||
                    456:        obj == cur_misc[WEAR_BRACERS]   || obj == cur_misc[WEAR_CLOAK]  ||
                    457:        obj == cur_misc[WEAR_GAUNTLET]  || obj == cur_misc[WEAR_NECKLACE]) {
                    458:
                    459:        return TRUE;
                    460:     }
                    461:
                    462:     /* Is it a "current" relic? */
                    463:     if (obj->o_type == RELIC) {
                    464:        switch (obj->o_which) {
                    465:            case MUSTY_DAGGER:
                    466:            case EMORI_CLOAK:
                    467:            case HEIL_ANKH:
                    468:            case YENDOR_AMULET:
                    469:            case HRUGGEK_MSTAR:
                    470:            case YEENOGHU_FLAIL:
                    471:                if (cur_relic[obj->o_which]) return TRUE;
                    472:        }
                    473:     }
                    474:
                    475:     return FALSE;
                    476: }
                    477:
                    478: 
                    479: /*
                    480:  * Look:
                    481:  *     A quick glance all around the player
                    482:  * wakeup: Should we wake up monsters
                    483:  * runend: At end of a run -- for mazes
                    484:  */
                    485:
                    486: void
                    487: look(bool wakeup, bool runend)
                    488: {
                    489:     register int x, y, radius;
                    490:     register char ch, och;
                    491:     register int oldx, oldy;
                    492:     register bool inpass, horiz, vert, do_light = FALSE, do_blank = FALSE;
                    493:     register int passcount = 0, curfloorcount = 0, nextfloorcount = 0;
                    494:     register struct room *rp;
                    495:     register int ey, ex;
                    496:
                    497:     inpass = ((rp = roomin(&hero)) == NULL); /* Are we in a passage? */
                    498:
                    499:     /* Are we moving vertically or horizontally? */
                    500:     if (runch == 'h' || runch == 'l') horiz = TRUE;
                    501:     else horiz = FALSE;
                    502:     if (runch == 'j' || runch == 'k') vert = TRUE;
                    503:     else vert = FALSE;
                    504:
                    505:     /* How far around himself can the player see? */
                    506:     if (levtype == OUTSIDE) {
                    507:        if (daytime) radius = 6;
                    508:        else if (lit_room(rp)) radius = 3;
                    509:        else radius = 1;
                    510:     }
                    511:     else radius = 1;
                    512:
                    513:     getyx(cw, oldy, oldx);     /* Save current position */
                    514:
                    515:     /* Blank out the floor around our last position and check for
                    516:      * moving out of a corridor in a maze.
                    517:      */
                    518:     if (levtype == OUTSIDE) do_blank = !daytime;
                    519:     else if (oldrp != NULL && !lit_room(oldrp) && off(player, ISBLIND))
                    520:            do_blank = TRUE;
                    521:
                    522:     /* Now move around the old position and blank things out */
                    523:     ey = player.t_oldpos.y + radius;
                    524:     ex = player.t_oldpos.x + radius;
                    525:     for (x = player.t_oldpos.x - radius; x <= ex; x++)
                    526:       if (x >= 0 && x < COLS)
                    527:        for (y = player.t_oldpos.y - radius; y <= ey; y++) {
                    528:            char savech;        /* Saves character in monster window */
                    529:
                    530:            if (y < 1 || y > LINES - 3) continue;
                    531:
                    532:            /* See what's there -- ignore monsters, just see what they're on */
                    533:            savech = CCHAR( mvwinch(mw, y, x) );
                    534:            waddch(mw, ' ');
                    535:            ch = show(y, x);
                    536:            mvwaddch(mw, y, x, savech); /* Restore monster */
                    537:
                    538:            if (do_blank && (y != hero.y || x != hero.x))
                    539:                switch (ch) {
                    540:                    case DOOR:
                    541:                    case SECRETDOOR:
                    542:                    case PASSAGE:
                    543:                    case STAIRS:
                    544:                    case TRAPDOOR:
                    545:                    case TELTRAP:
                    546:                    case BEARTRAP:
                    547:                    case SLEEPTRAP:
                    548:                    case ARROWTRAP:
                    549:                    case DARTTRAP:
                    550:                    case MAZETRAP:
                    551:                    case POOL:
                    552:                    case POST:
                    553:                    case '|':
                    554:                    case '-':
                    555:                    case WALL:
                    556:                        /* If there was a monster showing, make it disappear */
                    557:                        if (isalpha(savech)) mvwaddch(cw, y, x, ch);
                    558:                        break;
                    559:                    when FLOOR:
                    560:                    case FOREST:
                    561:                    default:
                    562:                        mvwaddch(cw, y, x, ' ');
                    563:                }
                    564:
                    565:            /* Moving out of a corridor? */
                    566:            if (levtype == MAZELEV && !ce(hero, player.t_oldpos) &&
                    567:                !running && !isrock(ch) &&  /* Not running and not a wall */
                    568:                ((vert && x != player.t_oldpos.x && y==player.t_oldpos.y) ||
                    569:                 (horiz && y != player.t_oldpos.y && x==player.t_oldpos.x)))
                    570:                    do_light = off(player, ISBLIND);
                    571:        }
                    572:
                    573:     /* Take care of unlighting a corridor */
                    574:     if (do_light && lit_room(rp)) light(&player.t_oldpos);
                    575:
                    576:     /* Are we coming or going between a wall and a corridor in a maze? */
                    577:     och = show(player.t_oldpos.y, player.t_oldpos.x);
                    578:     ch = show(hero.y, hero.x);
                    579:     if (levtype == MAZELEV &&
                    580:        ((isrock(och) && !isrock(ch)) || (isrock(ch) && !isrock(och)))) {
                    581:        do_light = off(player, ISBLIND); /* Light it up if not blind */
                    582:
                    583:        /* Unlight what we just saw */
                    584:        if (do_light && lit_room(&rooms[0])) light(&player.t_oldpos);
                    585:     }
                    586:
                    587:     /* Look around the player */
                    588:     ey = hero.y + radius;
                    589:     ex = hero.x + radius;
                    590:     for (x = hero.x - radius; x <= ex; x++)
                    591:        if (x >= 0 && x < COLS) for (y = hero.y - radius; y <= ey; y++) {
                    592:            if (y < 1 || y >= LINES - 2)
                    593:                continue;
                    594:            if (isalpha(mvwinch(mw, y, x)))
                    595:            {
                    596:                register struct linked_list *it;
                    597:                register struct thing *tp;
                    598:
                    599:                if (wakeup)
                    600:                    it = wake_monster(y, x);
                    601:                else
                    602:                    it = find_mons(y, x);
                    603:                tp = THINGPTR(it);
                    604:                tp->t_oldch = CCHAR( mvinch(y, x) );
                    605:                if (isatrap(tp->t_oldch)) {
                    606:                    register struct trap *trp = trap_at(y, x);
                    607:
                    608:                    tp->t_oldch = (trp->tr_flags & ISFOUND) ? tp->t_oldch
                    609:                                                            : trp->tr_show;
                    610:                }
                    611:                if (tp->t_oldch == FLOOR && !lit_room(rp) &&
                    612:                    off(player, ISBLIND))
                    613:                        tp->t_oldch = ' ';
                    614:            }
                    615:
                    616:            /*
                    617:             * Secret doors show as walls
                    618:             */
                    619:            if ((ch = show(y, x)) == SECRETDOOR)
                    620:                ch = secretdoor(y, x);
                    621:            /*
                    622:             * Don't show room walls if he is in a passage and
                    623:             * check for maze turns
                    624:             */
                    625:            if (off(player, ISBLIND))
                    626:            {
                    627:                if (y == hero.y && x == hero.x
                    628:                    || (inpass && (ch == '-' || ch == '|')))
                    629:                        continue;
                    630:
                    631:                /* Did we come to a crossroads in a maze? */
                    632:                if (levtype == MAZELEV &&
                    633:                    (runend || !ce(hero, player.t_oldpos)) &&
                    634:                    !isrock(ch) &&      /* Not a wall */
                    635:                    ((vert && x != hero.x && y == hero.y) ||
                    636:                     (horiz && y != hero.y && x == hero.x)))
                    637:                        /* Just came to a turn */
                    638:                        do_light = off(player, ISBLIND);
                    639:            }
                    640:            else if (y != hero.y || x != hero.x)
                    641:                continue;
                    642:
                    643:            wmove(cw, y, x);
                    644:            waddch(cw, ch);
                    645:            if (door_stop && !firstmove && running)
                    646:            {
                    647:                switch (runch)
                    648:                {
                    649:                    case 'h':
                    650:                        if (x == hero.x + 1)
                    651:                            continue;
                    652:                    when 'j':
                    653:                        if (y == hero.y - 1)
                    654:                            continue;
                    655:                    when 'k':
                    656:                        if (y == hero.y + 1)
                    657:                            continue;
                    658:                    when 'l':
                    659:                        if (x == hero.x - 1)
                    660:                            continue;
                    661:                    when 'y':
                    662:                        if ((x + y) - (hero.x + hero.y) >= 1)
                    663:                            continue;
                    664:                    when 'u':
                    665:                        if ((y - x) - (hero.y - hero.x) >= 1)
                    666:                            continue;
                    667:                    when 'n':
                    668:                        if ((x + y) - (hero.x + hero.y) <= -1)
                    669:                            continue;
                    670:                    when 'b':
                    671:                        if ((y - x) - (hero.y - hero.x) <= -1)
                    672:                            continue;
                    673:                }
                    674:                switch (ch)
                    675:                {
                    676:                    case DOOR:
                    677:                        if (x == hero.x || y == hero.y)
                    678:                            running = FALSE;
                    679:                        break;
                    680:                    case PASSAGE:
                    681:                        if (x == hero.x || y == hero.y)
                    682:                            passcount++;
                    683:                        break;
                    684:                    case FLOOR:
                    685:                        /* Stop by new passages in a maze (floor next to us) */
                    686:                        if ((levtype == MAZELEV) &&
                    687:                            !(hero.y == y && hero.x == x)) {
                    688:                            if (vert) { /* Moving vertically */
                    689:                                /* We have a passage on our row */
                    690:                                if (y == hero.y) curfloorcount++;
                    691:
                    692:                                /* Some passage on the next row */
                    693:                                else if (y != player.t_oldpos.y)
                    694:                                    nextfloorcount++;
                    695:                            }
                    696:                            else {      /* Moving horizontally */
                    697:                                /* We have a passage on our column */
                    698:                                if (x == hero.x) curfloorcount++;
                    699:
                    700:                                /* Some passage in the next column */
                    701:                                else if (x != player.t_oldpos.x)
                    702:                                    nextfloorcount++;
                    703:                            }
                    704:                        }
                    705:                    case '|':
                    706:                    case '-':
                    707:                    case ' ':
                    708:                        break;
                    709:                    default:
                    710:                        running = FALSE;
                    711:                        break;
                    712:                }
                    713:            }
                    714:        }
                    715:
                    716:     /* Have we passed a side passage, with multiple choices? */
                    717:     if (curfloorcount > 0 && nextfloorcount > 0) running = FALSE;
                    718:
                    719:     else if (door_stop && !firstmove && passcount > 1)
                    720:        running = FALSE;
                    721:
                    722:     /* Do we have to light up the area (just stepped into a new corridor)? */
                    723:     if (do_light && !running && lit_room(rp)) light(&hero);
                    724:
                    725:     mvwaddch(cw, hero.y, hero.x, PLAYER);
                    726:     wmove(cw, oldy, oldx);
                    727:     if (!ce(player.t_oldpos, hero)) {
                    728:        player.t_oldpos = hero; /* Don't change if we didn't move */
                    729:        oldrp = rp;
                    730:     }
                    731: }
                    732: 
                    733: /*
                    734:  * raise_level:
                    735:  *     The guy just magically went up a level.
                    736:  */
                    737:
                    738: void
                    739: raise_level(bool get_spells)
                    740: {
                    741:     unsigned long test;        /* Next level -- be sure it is not an overflow */
                    742:
                    743:     test = check_level(FALSE); /* Get next boundary */
                    744:
                    745:     /* Be sure it is higher than what we have no -- else overflow */
                    746:     if (test > pstats.s_exp) pstats.s_exp = test;
                    747:     check_level(get_spells);
                    748: }
                    749: 
                    750: /*
                    751:  * saving throw matrix for character saving throws
                    752:  * this table is indexed by char type and saving throw type
                    753:  */
                    754: static int st_matrix[5][5] = {
                    755: /* Poison,     Petrify,        wand,           Breath,         Magic */
                    756: { 14,          15,             16,             16,             17 },
                    757: { 14,          13,             11,             15,             12 },
                    758: { 10,          13,             14,             16,             15 },
                    759: { 13,          12,             14,             16,             15 },
                    760: { 14,          15,             16,             16,             17 }
                    761: };
                    762:
                    763: /*
                    764:  * save:
                    765:  *     See if a creature saves against something
                    766:  * which: which type of save
                    767:  * who: who is saving
                    768:  * adj: saving throw adjustment
                    769:  */
                    770: bool
                    771: save(int which, struct thing *who, int adj)
                    772: {
                    773:     register int need, level;
                    774:
                    775:     level = who->t_stats.s_lvl;
                    776:     need = st_matrix[who->t_ctype][which];
                    777:     switch (who->t_ctype) {
                    778:     case C_FIGHTER:
                    779:        need -= (level-1) / 2;
                    780:     when C_MAGICIAN:
                    781:        need -= 2 * (level-1) / 5;
                    782:     when C_CLERIC:
                    783:        need -= (level-1) / 3;
                    784:     when C_THIEF:
                    785:        need -= 2 * (level-1) / 4;
                    786:     when C_MONSTER:
                    787:        need -= level / 2;
                    788:     }
                    789:     /*
                    790:      * add in pluses against poison for execeptional constitution
                    791:      */
                    792:     if (which == VS_POISON && who->t_stats.s_const > 18)
                    793:        need -= (who->t_stats.s_const - 17) / 2;
                    794:     /*
                    795:      * does the player have a ring of protection on?
                    796:      */
                    797:     if (who == &player)
                    798:        need -= (min(ring_value(R_PROTECT),3)); /* no more than +3 bonus */
                    799:     /*
                    800:      * does the player have a cloak of protection on?
                    801:      */
                    802:     if (who == &player && cur_misc[WEAR_CLOAK])
                    803:        need -= (min(cur_misc[WEAR_CLOAK]->o_ac,3)); /* no more than +3 bonus */
                    804:     need -= adj;
                    805:     debug("need a %d to save", need);
                    806:     return (roll(1, 20) >= need);
                    807: }
                    808:
                    809: 
                    810: /*
                    811:  * secret_door:
                    812:  *     Figure out what a secret door looks like.
                    813:  */
                    814:
                    815: char
                    816: secretdoor(int y, int x)
                    817: {
                    818:     register int i;
                    819:     register struct room *rp;
                    820:     register coord *cpp;
                    821:     static coord cp;
                    822:
                    823:     cp.y = y;
                    824:     cp.x = x;
                    825:     cpp = &cp;
                    826:     for (rp = rooms, i = 0; i < MAXROOMS; rp++, i++)
                    827:        if (inroom(rp, cpp))
                    828:            if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
                    829:                return('-');
                    830:            else
                    831:                return('|');
                    832:
                    833:     return('p');
                    834: }
                    835: 
                    836: /*
                    837:  * copy string using unctrl for things
                    838:  */
                    839: void
                    840: strucpy(char *s1, char *s2, int len)
                    841: {
                    842:     const char *sp;
                    843:
                    844:     while (len--)
                    845:     {
                    846:        strcpy(s1, (sp = unctrl(*s2)));
                    847:        s1 += strlen(sp);
                    848:         s2++;
                    849:     }
                    850:     *s1 = '\0';
                    851: }
                    852: 
                    853: /*
                    854:  * tr_name:
                    855:  *     print the name of a trap
                    856:  */
                    857:
                    858: char *
                    859: tr_name(char ch)
                    860: {
                    861:     register char *s = NULL;
                    862:
                    863:     switch (ch)
                    864:     {
                    865:        case TRAPDOOR:
                    866:            s = terse ? "A trapdoor." : "You found a trapdoor.";
                    867:        when BEARTRAP:
                    868:            s = terse ? "A beartrap." : "You found a beartrap.";
                    869:        when SLEEPTRAP:
                    870:            s = terse ? "A sleeping gas trap.":"You found a sleeping gas trap.";
                    871:        when ARROWTRAP:
                    872:            s = terse ? "An arrow trap." : "You found an arrow trap.";
                    873:        when TELTRAP:
                    874:            s = terse ? "A teleport trap." : "You found a teleport trap.";
                    875:        when DARTTRAP:
                    876:            s = terse ? "A dart trap." : "You found a poison dart trap.";
                    877:        when POOL:
                    878:            s = terse ? "A shimmering pool." : "You found a shimmering pool";
                    879:        when MAZETRAP:
                    880:            s = terse ? "A maze entrance." : "You found a maze entrance";
                    881:     }
                    882:     return s;
                    883: }
                    884: 
                    885: /*
                    886:  * for printfs: if string starts with a vowel, return "n" for an "an"
                    887:  */
                    888: char *
                    889: vowelstr(char *str)
                    890: {
                    891:     switch (*str)
                    892:     {
                    893:        case 'a':
                    894:        case 'e':
                    895:        case 'i':
                    896:        case 'o':
                    897:        case 'u':
                    898:            return "n";
                    899:        default:
                    900:            return "";
                    901:     }
                    902: }
                    903: 
                    904: /*
                    905:  * waste_time:
                    906:  *     Do nothing but let other things happen
                    907:  */
                    908:
                    909: void
                    910: waste_time(void)
                    911: {
                    912:     if (inwhgt)                        /* if from wghtchk then done */
                    913:        return;
                    914:     do_daemons(BEFORE);
                    915:     do_fuses(BEFORE);
                    916:     do_daemons(AFTER);
                    917:     do_fuses(AFTER);
                    918: }

CVSweb