[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     ! 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