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

Annotation of early-roguelike/rogue5/misc.c, Revision 1.1

1.1     ! rubenllo    1: /*
        !             2:  * All sorts of miscellaneous routines
        !             3:  *
        !             4:  * @(#)misc.c  4.66 (Berkeley) 08/06/83
        !             5:  *
        !             6:  * Rogue: Exploring the Dungeons of Doom
        !             7:  * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * See the file LICENSE.TXT for full copyright and licensing information.
        !            11:  */
        !            12:
        !            13: #include <stdlib.h>
        !            14: #include <curses.h>
        !            15: #include <string.h>
        !            16: #include <ctype.h>
        !            17: #include "rogue.h"
        !            18:
        !            19: /*
        !            20:  * look:
        !            21:  *     A quick glance all around the player
        !            22:  */
        !            23: #undef DEBUG
        !            24:
        !            25:
        !            26: void
        !            27: look(int wakeup)
        !            28: {
        !            29:     int x, y;
        !            30:     chtype ch;
        !            31:     THING *tp;
        !            32:     PLACE *pp;
        !            33:     struct room *rp;
        !            34:     int ey, ex;
        !            35:     int passcount;
        !            36:     int pfl, *fp, pch;
        !            37:     int sy, sx, sumhero = 0, diffhero = 0;
        !            38: # ifdef DEBUG
        !            39:     static int done = FALSE;
        !            40:
        !            41:     if (done)
        !            42:        return;
        !            43:     done = TRUE;
        !            44: # endif /* DEBUG */
        !            45:     passcount = 0;
        !            46:     rp = proom;
        !            47:     if (!ce(oldpos, hero))
        !            48:     {
        !            49:        erase_lamp(&oldpos, oldrp);
        !            50:        oldpos = hero;
        !            51:        oldrp = rp;
        !            52:     }
        !            53:     ey = hero.y + 1;
        !            54:     ex = hero.x + 1;
        !            55:     sx = hero.x - 1;
        !            56:     sy = hero.y - 1;
        !            57:     if (door_stop && !firstmove && running)
        !            58:     {
        !            59:        sumhero = hero.y + hero.x;
        !            60:        diffhero = hero.y - hero.x;
        !            61:     }
        !            62:     pp = INDEX(hero.y, hero.x);
        !            63:     pch = pp->p_ch;
        !            64:     pfl = pp->p_flags;
        !            65:
        !            66:     for (y = sy; y <= ey; y++)
        !            67:        if (y > 0 && y < NUMLINES - 1) for (x = sx; x <= ex; x++)
        !            68:        {
        !            69:            if (x < 0 || x >= NUMCOLS)
        !            70:                continue;
        !            71:            if (!on(player, ISBLIND))
        !            72:            {
        !            73:                if (y == hero.y && x == hero.x)
        !            74:                    continue;
        !            75:            }
        !            76:
        !            77:            pp = INDEX(y, x);
        !            78:            ch = pp->p_ch;
        !            79:            if (ch == ' ')              /* nothing need be done with a ' ' */
        !            80:                    continue;
        !            81:            fp = &pp->p_flags;
        !            82:            if (pch != DOOR && ch != DOOR)
        !            83:                if ((pfl & F_PASS) != (*fp & F_PASS))
        !            84:                    continue;
        !            85:            if (((*fp & F_PASS) || ch == DOOR) &&
        !            86:                 ((pfl & F_PASS) || pch == DOOR))
        !            87:            {
        !            88:                if (hero.x != x && hero.y != y &&
        !            89:                    !step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x)))
        !            90:                        continue;
        !            91:            }
        !            92:
        !            93:            if ((tp = pp->p_monst) == NULL)
        !            94:                ch = trip_ch(y, x, ch);
        !            95:            else
        !            96:                if (on(player, SEEMONST) && on(*tp, ISINVIS))
        !            97:                {
        !            98:                    if (door_stop && !firstmove)
        !            99:                        running = FALSE;
        !           100:                    continue;
        !           101:                }
        !           102:                else
        !           103:                {
        !           104:                    if (wakeup)
        !           105:                        wake_monster(y, x);
        !           106:                    if (see_monst(tp))
        !           107:                    {
        !           108:                        if (on(player, ISHALU))
        !           109:                            ch = rnd(26) + 'A';
        !           110:                        else
        !           111:                            ch = tp->t_disguise;
        !           112:                    }
        !           113:                }
        !           114:            if (on(player, ISBLIND) && (y != hero.y || x != hero.x))
        !           115:                continue;
        !           116:
        !           117:            move(y, x);
        !           118:
        !           119:            if ((proom->r_flags & ISDARK) && !see_floor && ch == FLOOR)
        !           120:                ch = ' ';
        !           121:
        !           122:            if (tp != NULL || ch != CCHAR( inch() ))
        !           123:                addch(ch);
        !           124:
        !           125:            if (door_stop && !firstmove && running)
        !           126:            {
        !           127:                switch (runch)
        !           128:                {
        !           129:                    case 'h':
        !           130:                        if (x == ex)
        !           131:                            continue;
        !           132:                    when 'j':
        !           133:                        if (y == sy)
        !           134:                            continue;
        !           135:                    when 'k':
        !           136:                        if (y == ey)
        !           137:                            continue;
        !           138:                    when 'l':
        !           139:                        if (x == sx)
        !           140:                            continue;
        !           141:                    when 'y':
        !           142:                        if ((y + x) - sumhero >= 1)
        !           143:                            continue;
        !           144:                    when 'u':
        !           145:                        if ((y - x) - diffhero >= 1)
        !           146:                            continue;
        !           147:                    when 'n':
        !           148:                        if ((y + x) - sumhero <= -1)
        !           149:                            continue;
        !           150:                    when 'b':
        !           151:                        if ((y - x) - diffhero <= -1)
        !           152:                            continue;
        !           153:                }
        !           154:                switch (ch)
        !           155:                {
        !           156:                    case DOOR:
        !           157:                        if (x == hero.x || y == hero.y)
        !           158:                            running = FALSE;
        !           159:                        break;
        !           160:                    case PASSAGE:
        !           161:                        if (x == hero.x || y == hero.y)
        !           162:                            passcount++;
        !           163:                        break;
        !           164:                    case FLOOR:
        !           165:                    case '|':
        !           166:                    case '-':
        !           167:                    case ' ':
        !           168:                        break;
        !           169:                    default:
        !           170:                        running = FALSE;
        !           171:                        break;
        !           172:                }
        !           173:            }
        !           174:        }
        !           175:     if (door_stop && !firstmove && passcount > 1)
        !           176:        running = FALSE;
        !           177:     if (!running || !jump)
        !           178:        mvaddch(hero.y, hero.x, PLAYER);
        !           179: # ifdef DEBUG
        !           180:     done = FALSE;
        !           181: # endif /* DEBUG */
        !           182: }
        !           183:
        !           184: /*
        !           185:  * trip_ch:
        !           186:  *     Return the character appropriate for this space, taking into
        !           187:  *     account whether or not the player is tripping.
        !           188:  */
        !           189: int
        !           190: trip_ch(int y, int x, int ch)
        !           191: {
        !           192:     if (on(player, ISHALU) && after)
        !           193:        switch (ch)
        !           194:        {
        !           195:            case FLOOR:
        !           196:            case ' ':
        !           197:            case PASSAGE:
        !           198:            case '-':
        !           199:            case '|':
        !           200:            case DOOR:
        !           201:            case TRAP:
        !           202:                break;
        !           203:            default:
        !           204:                if (y != stairs.y || x != stairs.x || !seenstairs)
        !           205:                    ch = rnd_thing();
        !           206:                break;
        !           207:        }
        !           208:     return ch;
        !           209: }
        !           210:
        !           211: /*
        !           212:  * erase_lamp:
        !           213:  *     Erase the area shown by a lamp in a dark room.
        !           214:  */
        !           215:
        !           216: void
        !           217: erase_lamp(const coord *pos, const struct room *rp)
        !           218: {
        !           219:     int y, x, ey, sy, ex;
        !           220:
        !           221:     if (!(see_floor && (rp->r_flags & (ISGONE|ISDARK)) == ISDARK
        !           222:        && !on(player,ISBLIND)))
        !           223:            return;
        !           224:
        !           225:     ey = pos->y + 1;
        !           226:     ex = pos->x + 1;
        !           227:     sy = pos->y - 1;
        !           228:     for (x = pos->x - 1; x <= ex; x++)
        !           229:        for (y = sy; y <= ey; y++)
        !           230:        {
        !           231:            if (y == hero.y && x == hero.x)
        !           232:                continue;
        !           233:            move(y, x);
        !           234:            if (CCHAR( inch() ) == FLOOR)
        !           235:                addch(' ');
        !           236:        }
        !           237: }
        !           238:
        !           239: /*
        !           240:  * show_floor:
        !           241:  *     Should we show the floor in her room at this time?
        !           242:  */
        !           243: int
        !           244: show_floor(void)
        !           245: {
        !           246:     if ((proom->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(player, ISBLIND))
        !           247:        return see_floor;
        !           248:     else
        !           249:        return TRUE;
        !           250: }
        !           251:
        !           252: /*
        !           253:  * find_obj:
        !           254:  *     Find the unclaimed object at y, x
        !           255:  */
        !           256: THING *
        !           257: find_obj(int y, int x)
        !           258: {
        !           259:     THING *obj;
        !           260:
        !           261:     for (obj = lvl_obj; obj != NULL; obj = next(obj))
        !           262:     {
        !           263:        if (obj->o_pos.y == y && obj->o_pos.x == x)
        !           264:                return obj;
        !           265:     }
        !           266: #ifdef MASTER
        !           267:     sprintf(prbuf, "Non-object %d,%d", y, x);
        !           268:     msg(prbuf);
        !           269:     return NULL;
        !           270: #else
        !           271:     /* NOTREACHED */
        !           272:     return NULL;
        !           273: #endif
        !           274: }
        !           275:
        !           276: /*
        !           277:  * eat:
        !           278:  *     She wants to eat something, so let her try
        !           279:  */
        !           280:
        !           281: void
        !           282: eat(void)
        !           283: {
        !           284:     THING *obj;
        !           285:
        !           286:     if ((obj = get_item("eat", FOOD)) == NULL)
        !           287:        return;
        !           288:     if (obj->o_type != FOOD)
        !           289:     {
        !           290:        if (!terse)
        !           291:            msg("ugh, you would get ill if you ate that");
        !           292:        else
        !           293:            msg("that's Inedible!");
        !           294:        return;
        !           295:     }
        !           296:     if (food_left < 0)
        !           297:        food_left = 0;
        !           298:     if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE)
        !           299:        food_left = STOMACHSIZE;
        !           300:     hungry_state = 0;
        !           301:     if (obj == cur_weapon)
        !           302:        cur_weapon = NULL;
        !           303:     if (obj->o_which == 1)
        !           304:        msg("my, that was a yummy %s", fruit);
        !           305:     else
        !           306:        if (rnd(100) > 70)
        !           307:        {
        !           308:            pstats.s_exp++;
        !           309:            msg("%s, this food tastes awful", choose_str("bummer", "yuk"));
        !           310:            check_level();
        !           311:        }
        !           312:        else
        !           313:            msg("%s, that tasted good", choose_str("oh, wow", "yum"));
        !           314:     leave_pack(obj, FALSE, FALSE);
        !           315: }
        !           316:
        !           317: /*
        !           318:  * check_level:
        !           319:  *     Check to see if the guy has gone up a level.
        !           320:  */
        !           321:
        !           322: void
        !           323: check_level(void)
        !           324: {
        !           325:     int i, add, olevel;
        !           326:
        !           327:     for (i = 0; e_levels[i] != 0; i++)
        !           328:        if (e_levels[i] > pstats.s_exp)
        !           329:            break;
        !           330:     i++;
        !           331:     olevel = pstats.s_lvl;
        !           332:     pstats.s_lvl = i;
        !           333:     if (i > olevel)
        !           334:     {
        !           335:        add = roll(i - olevel, 10);
        !           336:        max_hp += add;
        !           337:        pstats.s_hpt += add;
        !           338:        msg("welcome to level %d", i);
        !           339:     }
        !           340: }
        !           341:
        !           342: /*
        !           343:  * chg_str:
        !           344:  *     used to modify the playes strength.  It keeps track of the
        !           345:  *     highest it has been, just in case
        !           346:  */
        !           347:
        !           348: void
        !           349: chg_str(int amt)
        !           350: {
        !           351:     int comp;
        !           352:
        !           353:     if (amt == 0)
        !           354:        return;
        !           355:     add_str(&pstats.s_str, amt);
        !           356:     comp = pstats.s_str;
        !           357:     if (ISRING(LEFT, R_ADDSTR))
        !           358:        add_str(&comp, -cur_ring[LEFT]->o_arm);
        !           359:     if (ISRING(RIGHT, R_ADDSTR))
        !           360:        add_str(&comp, -cur_ring[RIGHT]->o_arm);
        !           361:     if (comp > max_stats.s_str)
        !           362:        max_stats.s_str = comp;
        !           363: }
        !           364:
        !           365: /*
        !           366:  * add_str:
        !           367:  *     Perform the actual add, checking upper and lower bound limits
        !           368:  */
        !           369: void
        !           370: add_str(int *sp, int amt)
        !           371: {
        !           372:     if ((*sp += amt) < 3)
        !           373:        *sp = 3;
        !           374:     else if (*sp > 31)
        !           375:        *sp = 31;
        !           376: }
        !           377:
        !           378: /*
        !           379:  * add_haste:
        !           380:  *     Add a haste to the player
        !           381:  */
        !           382: int
        !           383: add_haste(int potion)
        !           384: {
        !           385:     if (on(player, ISHASTE))
        !           386:     {
        !           387:        no_command += rnd(8);
        !           388:        player.t_flags &= ~(ISRUN|ISHASTE);
        !           389:        extinguish(nohaste);
        !           390:        msg("you faint from exhaustion");
        !           391:        return FALSE;
        !           392:     }
        !           393:     else
        !           394:     {
        !           395:        player.t_flags |= ISHASTE;
        !           396:        if (potion)
        !           397:            fuse(nohaste, 0, rnd(4)+4, AFTER);
        !           398:        return TRUE;
        !           399:     }
        !           400: }
        !           401:
        !           402: /*
        !           403:  * aggravate:
        !           404:  *     Aggravate all the monsters on this level
        !           405:  */
        !           406:
        !           407: void
        !           408: aggravate(void)
        !           409: {
        !           410:     THING *mp;
        !           411:
        !           412:     for (mp = mlist; mp != NULL; mp = next(mp))
        !           413:        runto(&mp->t_pos);
        !           414: }
        !           415:
        !           416: /*
        !           417:  * vowelstr:
        !           418:  *      For printfs: if string starts with a vowel, return "n" for an
        !           419:  *     "an".
        !           420:  */
        !           421: char *
        !           422: vowelstr(const char *str)
        !           423: {
        !           424:     switch (*str)
        !           425:     {
        !           426:        case 'a': case 'A':
        !           427:        case 'e': case 'E':
        !           428:        case 'i': case 'I':
        !           429:        case 'o': case 'O':
        !           430:        case 'u': case 'U':
        !           431:            return "n";
        !           432:        default:
        !           433:            return "";
        !           434:     }
        !           435: }
        !           436:
        !           437: /*
        !           438:  * is_current:
        !           439:  *     See if the object is one of the currently used items
        !           440:  */
        !           441: int
        !           442: is_current(const THING *obj)
        !           443: {
        !           444:     if (obj == NULL)
        !           445:        return FALSE;
        !           446:     if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
        !           447:        || obj == cur_ring[RIGHT])
        !           448:     {
        !           449:        if (!terse)
        !           450:            addmsg("That's already ");
        !           451:        msg("in use");
        !           452:        return TRUE;
        !           453:     }
        !           454:     return FALSE;
        !           455: }
        !           456:
        !           457: /*
        !           458:  * get_dir:
        !           459:  *      Set up the direction co_ordinate for use in varios "prefix"
        !           460:  *     commands
        !           461:  */
        !           462: int
        !           463: get_dir(void)
        !           464: {
        !           465:     char *prompt;
        !           466:     int gotit;
        !           467:     static coord last_delt= {0,0};
        !           468:
        !           469:     if (again && last_dir != '\0')
        !           470:     {
        !           471:        delta.y = last_delt.y;
        !           472:        delta.x = last_delt.x;
        !           473:        dir_ch = last_dir;
        !           474:     }
        !           475:     else
        !           476:     {
        !           477:        if (!terse)
        !           478:            msg(prompt = "which direction? ");
        !           479:        else
        !           480:            prompt = "direction: ";
        !           481:        do
        !           482:        {
        !           483:            gotit = TRUE;
        !           484:            switch (dir_ch = readchar())
        !           485:            {
        !           486:                case 'h': case'H': delta.y =  0; delta.x = -1;
        !           487:                when 'j': case'J': delta.y =  1; delta.x =  0;
        !           488:                when 'k': case'K': delta.y = -1; delta.x =  0;
        !           489:                when 'l': case'L': delta.y =  0; delta.x =  1;
        !           490:                when 'y': case'Y': delta.y = -1; delta.x = -1;
        !           491:                when 'u': case'U': delta.y = -1; delta.x =  1;
        !           492:                when 'b': case'B': delta.y =  1; delta.x = -1;
        !           493:                when 'n': case'N': delta.y =  1; delta.x =  1;
        !           494:                when ESCAPE: last_dir = '\0'; reset_last(); msg(""); return FALSE;
        !           495:                otherwise:
        !           496:                    mpos = 0;
        !           497:                    msg(prompt);
        !           498:                    gotit = FALSE;
        !           499:            }
        !           500:        } until (gotit);
        !           501:        if (isupper(dir_ch))
        !           502:            dir_ch = tolower(dir_ch);
        !           503:        last_dir = dir_ch;
        !           504:        last_delt.y = delta.y;
        !           505:        last_delt.x = delta.x;
        !           506:     }
        !           507:     if (on(player, ISHUH) && rnd(5) == 0)
        !           508:        do
        !           509:        {
        !           510:            delta.y = rnd(3) - 1;
        !           511:            delta.x = rnd(3) - 1;
        !           512:        } while (delta.y == 0 && delta.x == 0);
        !           513:     mpos = 0;
        !           514:     msg("");
        !           515:     return TRUE;
        !           516: }
        !           517:
        !           518: /*
        !           519:  * sign:
        !           520:  *     Return the sign of the number
        !           521:  */
        !           522: int
        !           523: sign(int nm)
        !           524: {
        !           525:     if (nm < 0)
        !           526:        return -1;
        !           527:     else
        !           528:        return (nm > 0);
        !           529: }
        !           530:
        !           531: /*
        !           532:  * spread:
        !           533:  *     Give a spread around a given number (+/- 20%)
        !           534:  */
        !           535: int
        !           536: spread(int nm)
        !           537: {
        !           538:     return nm - nm / 20 + rnd(nm / 10);
        !           539: }
        !           540:
        !           541: /*
        !           542:  * call_it:
        !           543:  *     Call an object something after use.
        !           544:  */
        !           545:
        !           546: void
        !           547: call_it(struct obj_info *info)
        !           548: {
        !           549:     if (info->oi_know)
        !           550:     {
        !           551:        if (info->oi_guess)
        !           552:        {
        !           553:            free(info->oi_guess);
        !           554:            info->oi_guess = NULL;
        !           555:        }
        !           556:     }
        !           557:     else if (!info->oi_guess)
        !           558:     {
        !           559:        msg(terse ? "call it: " : "what do you want to call it? ");
        !           560:        if (get_str(prbuf, stdscr) == NORM)
        !           561:        {
        !           562:            if (info->oi_guess != NULL)
        !           563:                free(info->oi_guess);
        !           564:            info->oi_guess = malloc(strlen(prbuf) + 1);
        !           565:                if (info->oi_guess != NULL)
        !           566:                        strcpy(info->oi_guess, prbuf);
        !           567:        }
        !           568:        msg("");
        !           569:     }
        !           570: }
        !           571:
        !           572: /*
        !           573:  * rnd_thing:
        !           574:  *     Pick a random thing appropriate for this level
        !           575:  */
        !           576: int
        !           577: rnd_thing(void)
        !           578: {
        !           579:     int i;
        !           580:     int thing_list[] = {
        !           581:        POTION, SCROLL, RING, STICK, FOOD, WEAPON, ARMOR, STAIRS, GOLD, AMULET
        !           582:     };
        !           583:
        !           584:     if (level >= AMULETLEVEL)
        !           585:         i = rnd(sizeof thing_list / sizeof (int));
        !           586:     else
        !           587:         i = rnd(sizeof thing_list / sizeof (int) - 1);
        !           588:     return thing_list[i];
        !           589: }
        !           590:
        !           591: /*
        !           592:  str str:
        !           593:  *     Choose the first or second string depending on whether it the
        !           594:  *     player is tripping
        !           595:  */
        !           596: const char *
        !           597: choose_str(const char *ts, const char *ns)
        !           598: {
        !           599:        return (on(player, ISHALU) ? ts : ns);
        !           600: }

CVSweb