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

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

1.1       rubenllo    1: /*
                      2:  * new_level: Dig and draw a new level
                      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: #define TERRASAVE 3
                     18:
                     19: void put_things(LEVTYPE ltype);
                     20:
                     21: /* ltype designates type of level to create */
                     22: void
                     23: new_level(LEVTYPE ltype)
                     24: {
                     25:     register int rm = 0, i, cnt;
                     26:     register char ch;
                     27:     register struct linked_list *item;
                     28:     register struct thing *tp;
                     29:     register struct object *obj;
                     30:     int waslit = 0;    /* Was the previous outside level lit? */
                     31:     int starty = 0, startx = 0, deltay = 0, deltax = 0;
                     32:     bool fresh=TRUE, vert = 0, top;
                     33:     struct room *rp;
                     34:     struct linked_list *nitem, *savmonst=NULL, *savitems=NULL;
                     35:     coord stairs = { 0, 0 };
                     36:
                     37:     if (wizard) {
                     38:        msg("Turns: %d", turns);        /* Number of turns for last level */
                     39:        mpos = 0;
                     40:     }
                     41:
                     42:     /* Start player off right */
                     43:     turn_off(player, ISHELD);
                     44:     turn_off(player, ISFLEE);
                     45:     extinguish(suffocate);
                     46:     hold_count = 0;
                     47:     trap_tries = 0;
                     48:
                     49:     /* Are we just entering a dungeon?  If so, how big is it? */
                     50:     if (ltype != OUTSIDE && nfloors < 0) nfloors = HARDER+10  + rnd(11);
                     51:
                     52:     if (level > max_level)
                     53:        max_level = level;
                     54:
                     55:     /* Are we starting a new outside level? */
                     56:     if (ltype == OUTSIDE) {
                     57:        register int i, j;
                     58:
                     59:        /* Save some information prior to clearing the screen */
                     60:        if (level == -1 || mvinch(hero.y, hero.x)  == '-') vert = TRUE;
                     61:        else vert = FALSE;
                     62:
                     63:        if (level == -1) {
                     64:            fresh = TRUE;
                     65:            starty = 2;
                     66:            startx = 1;
                     67:            deltay = deltax = 1;
                     68:            level = 0;  /* Restore the level */
                     69:        }
                     70:        else {  /* Copy several lines of the terrain to the other end */
                     71:            char cch;   /* Copy character */
                     72:
                     73:            /* Was the area dark (not magically lit)? */
                     74:            if (!(rooms[0].r_flags & ISDARK)) waslit = 1;
                     75:
                     76:            fresh = FALSE;
                     77:            if ((vert && hero.y == 1) || (!vert && hero.x == 0)) top = TRUE;
                     78:            else top = FALSE;
                     79:            for (i=0; i<TERRASAVE; i++) {
                     80:                if (vert)
                     81:                    for (j=1; j<COLS-1; j++) {
                     82:                        if (top) {
                     83:                            cch = CCHAR( mvinch(i+2, j) );
                     84:                            mvaddch(LINES-6+i, j, cch);
                     85:                        }
                     86:                        else {
                     87:                            cch = CCHAR( mvinch(LINES-4-i, j) );
                     88:                            mvaddch(4-i, j, cch);
                     89:                        }
                     90:                    }
                     91:                else
                     92:                    for (j=2; j<LINES-3; j++) {
                     93:                        if (top) {
                     94:                            cch = CCHAR( mvinch(j, i+1) );
                     95:                            mvaddch(j, COLS-4+i, cch);
                     96:                        }
                     97:                        else {
                     98:                            cch = CCHAR( mvinch(j, COLS-2-i) );
                     99:                            mvaddch(j, 3-i, cch);
                    100:                        }
                    101:                    }
                    102:            }
                    103:
                    104:            if (vert) {
                    105:                startx = deltax = 1;
                    106:                if (top) {
                    107:                    starty = LINES-4-TERRASAVE;
                    108:                    deltay = -1;
                    109:                }
                    110:                else {
                    111:                    starty = TERRASAVE + 2;
                    112:                    deltay = 1;
                    113:                }
                    114:            }
                    115:            else {
                    116:                starty = 2;
                    117:                deltay = 1;
                    118:                if (top) {
                    119:                    startx = COLS-2-TERRASAVE;
                    120:                    deltax = -1;
                    121:                }
                    122:                else {
                    123:                    deltax = 1;
                    124:                    startx = TERRASAVE + 1;
                    125:                }
                    126:            }
                    127:
                    128:            /* Check if any monsters should be saved */
                    129:            for (item = mlist; item != NULL; item = nitem) {
                    130:                nitem = next(item);
                    131:                tp = THINGPTR(item);
                    132:                if (vert) {
                    133:                    if (top) {
                    134:                        if (tp->t_pos.y < TERRASAVE + 2)
                    135:                            tp->t_pos.y += LINES - 5 - TERRASAVE;
                    136:                        else continue;
                    137:                    }
                    138:                    else {
                    139:                        if (tp->t_pos.y > LINES - 4 - TERRASAVE)
                    140:                            tp->t_pos.y += 5 + TERRASAVE - LINES;
                    141:                        else continue;
                    142:                    }
                    143:                }
                    144:                else {
                    145:                    if (top) {
                    146:                        if (tp->t_pos.x < TERRASAVE + 1)
                    147:                            tp->t_pos.x += COLS - 2 - TERRASAVE;
                    148:                        else continue;
                    149:                    }
                    150:                    else {
                    151:                        if (tp->t_pos.x > COLS - 2 - TERRASAVE)
                    152:                            tp->t_pos.x += 2 + TERRASAVE - COLS;
                    153:                        else continue;
                    154:                    }
                    155:                }
                    156:                detach(mlist, item);
                    157:                attach(savmonst, item);
                    158:            }
                    159:
                    160:            /* Check if any treasure should be saved */
                    161:            for (item = lvl_obj; item != NULL; item = nitem) {
                    162:                nitem = next(item);
                    163:                obj = OBJPTR(item);
                    164:                if (vert) {
                    165:                    if (top) {
                    166:                        if (obj->o_pos.y < TERRASAVE + 2)
                    167:                            obj->o_pos.y += LINES - 5 - TERRASAVE;
                    168:                        else continue;
                    169:                    }
                    170:                    else {
                    171:                        if (obj->o_pos.y > LINES - 4 - TERRASAVE)
                    172:                            obj->o_pos.y += 5 + TERRASAVE - LINES;
                    173:                        else continue;
                    174:                    }
                    175:                }
                    176:                else {
                    177:                    if (top) {
                    178:                        if (obj->o_pos.x < TERRASAVE + 1)
                    179:                            obj->o_pos.x += COLS - 2 - TERRASAVE;
                    180:                        else continue;
                    181:                    }
                    182:                    else {
                    183:                        if (obj->o_pos.x > COLS - 2 - TERRASAVE)
                    184:                            obj->o_pos.x += 2 + TERRASAVE - COLS;
                    185:                        else continue;
                    186:                    }
                    187:                }
                    188:                detach(lvl_obj, item);
                    189:                attach(savitems, item);
                    190:            }
                    191:        }
                    192:     }
                    193:
                    194:
                    195:     wclear(cw);
                    196:     wclear(mw);
                    197:     if (fresh) clear();
                    198:     /*
                    199:      * check to see if he missed a UNIQUE, If he did then put it back
                    200:      * in the monster table for next time
                    201:      */
                    202:     for (item = mlist; item != NULL; item = next(item)) {
                    203:        tp = THINGPTR(item);
                    204:        if (on(*tp, ISUNIQUE))
                    205:            monsters[tp->t_index].m_normal = TRUE;
                    206:     }
                    207:     /*
                    208:      * Free up the monsters on the last level
                    209:      */
                    210:     t_free_list(monst_dead);
                    211:     t_free_list(mlist);
                    212:     o_free_list(lvl_obj);              /* Free up previous objects (if any) */
                    213:     for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
                    214:        t_free_list(rp->r_exit);        /* Free up the exit lists */
                    215:
                    216:     levtype = ltype;
                    217:     foods_this_level = 0;              /* food for hero this level */
                    218:     if (ltype == POSTLEV) {
                    219:        do_post();                      /* do post stuff */
                    220:     }
                    221:     else if (ltype == MAZELEV) {
                    222:        do_maze();
                    223:        no_food++;
                    224:        put_things(ltype);              /* Place objects (if any) */
                    225:     }
                    226:     else if (ltype == OUTSIDE) {
                    227:        init_terrain();
                    228:        do_terrain(starty, startx, deltay, deltax, (bool) (fresh || !vert));
                    229:        no_food++;
                    230:        put_things(ltype);
                    231:
                    232:        /* Should we magically light this area? */
                    233:        if (waslit) rooms[0].r_flags &= ~ISDARK;
                    234:     }
                    235:     else {
                    236:        do_rooms();                     /* Draw rooms */
                    237:        do_passages();                  /* Draw passages */
                    238:        no_food++;
                    239:        put_things(ltype);              /* Place objects (if any) */
                    240:     }
                    241:     /*
                    242:      * Place the staircase down.  Only a small chance for an outside stairway.
                    243:      */
                    244:     if (ltype != OUTSIDE || roll(1, 4) == 4) {
                    245:        cnt = 0;
                    246:        do {
                    247:            rm = rnd_room();
                    248:            rnd_pos(&rooms[rm], &stairs);
                    249:        } until (mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
                    250:        addch(STAIRS);
                    251:     }
                    252:     /*
                    253:      * maybe add a trading post
                    254:      */
                    255:     if (level > 5 && rnd(11) == 7 && ltype == NORMLEV) {
                    256:        cnt = 0;
                    257:        do {
                    258:            rm = rnd_room();
                    259:            if (rooms[rm].r_flags & ISTREAS)
                    260:                continue;
                    261:            rnd_pos(&rooms[rm], &stairs);
                    262:        } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
                    263:        addch(POST);
                    264:     }
                    265:     if (ltype != POSTLEV) {    /* Add monsters that fell through */
                    266:        nitem = tlist;
                    267:        while (nitem != NULL) {
                    268:            item = nitem;
                    269:            nitem = next(item); /* because detach and attach mess up ptrs */
                    270:            tp = THINGPTR(item);
                    271:            cnt = 0;
                    272:            do {
                    273:                rm = rnd_room();
                    274:                rnd_pos(&rooms[rm], &tp->t_pos);
                    275:            } until (cnt++ > 5000 || winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
                    276:            mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
                    277:            tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
                    278:
                    279:            /*
                    280:             * If it has a fire, mark it
                    281:             */
                    282:            if (on(*tp, HASFIRE)) {
                    283:                register struct linked_list *fire_item;
                    284:
                    285:                fire_item = creat_item();
                    286:                ldata(fire_item) = (char *) tp;
                    287:                attach(rooms[rm].r_fires, fire_item);
                    288:                rooms[rm].r_flags |= HASFIRE;
                    289:            }
                    290:            turn_off(*tp, ISELSEWHERE);
                    291:            detach(tlist, item);
                    292:            attach(mlist, item);
                    293:        }
                    294:     }
                    295:
                    296:     /* Restore any saved monsters */
                    297:     for (item = savmonst; item != NULL; item = nitem) {
                    298:        nitem = next(item);
                    299:        tp = THINGPTR(item);
                    300:        mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
                    301:        tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
                    302:
                    303:        /*
                    304:         * If it has a fire, mark it
                    305:         */
                    306:        if (on(*tp, HASFIRE)) {
                    307:            register struct linked_list *fire_item;
                    308:
                    309:            fire_item = creat_item();
                    310:            ldata(fire_item) = (char *) tp;
                    311:            attach(rooms[rm].r_fires, fire_item);
                    312:            rooms[rm].r_flags |= HASFIRE;
                    313:        }
                    314:
                    315:        detach(savmonst, item);
                    316:        attach(mlist, item);
                    317:     }
                    318:
                    319:     /* Restore any saved objects */
                    320:     for(item = savitems; item != NULL; item = nitem) {
                    321:        nitem = next(item);
                    322:        obj = OBJPTR(item);
                    323:        mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
                    324:        detach(savitems, item);
                    325:        attach(lvl_obj, item);
                    326:     }
                    327:
                    328:
                    329:     /*
                    330:      * Place the traps (except for trading post)
                    331:      */
                    332:     ntraps = 0;        /* No traps yet */
                    333:     if (levtype == NORMLEV) {
                    334:        if (rnd(10) < vlevel) {
                    335:            ntraps = rnd(vlevel/4)+1;
                    336:            if (ntraps > MAXTRAPS)
                    337:                ntraps = MAXTRAPS;
                    338:            i = ntraps;
                    339:            while (i--)
                    340:            {
                    341:                cnt = 0;
                    342:                do {
                    343:                    rm = rnd_room();
                    344:                    if (rooms[rm].r_flags & ISTREAS)
                    345:                        continue;
                    346:                    rnd_pos(&rooms[rm], &stairs);
                    347:                } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
                    348:
                    349:                traps[i].tr_flags = 0;
                    350:
                    351:                /* If we are at the bottom, we can't set a trap door */
                    352:                if (level >= nfloors) ch = (char) rnd(7) + 1;
                    353:                else ch = (char) rnd(8);
                    354:
                    355:                switch((int) ch) {
                    356:                    case 0: ch = TRAPDOOR;
                    357:                    when 1: ch = BEARTRAP;
                    358:                    when 2: ch = SLEEPTRAP;
                    359:                    when 3: ch = ARROWTRAP;
                    360:                    when 4: ch = TELTRAP;
                    361:                    when 5: ch = DARTTRAP;
                    362:                    when 6: ch = POOL;
                    363:                            traps[i].tr_flags = ISFOUND;
                    364:                    when 7: ch = MAZETRAP;
                    365:                }
                    366:                addch(ch);
                    367:                traps[i].tr_type = ch;
                    368:                traps[i].tr_show = FLOOR;
                    369:                traps[i].tr_pos = stairs;
                    370:            }
                    371:        }
                    372:     }
                    373:     if (fresh) {       /* A whole new picture */
                    374:        cnt = 0;
                    375:        do {
                    376:            rm = rnd_room();
                    377:            if (rooms[rm].r_flags & ISTREAS)
                    378:                continue;
                    379:            rnd_pos(&rooms[rm], &hero);
                    380:        } until(        cnt++ > 5000 ||
                    381:                    (winat(hero.y, hero.x) == FLOOR &&
                    382:                     DISTANCE(hero.y, hero.x, stairs.y, stairs.x) > 16));
                    383:     }
                    384:     else {             /* We're extending into an adjacent outside plane */
                    385:        rm = 0;
                    386:        if (vert) {
                    387:            if (hero.y == 1) hero.y = LINES - 3 - TERRASAVE; /* Top to bottom */
                    388:            else hero.y = TERRASAVE + 1;        /* Bottom to top */
                    389:        }
                    390:        else {
                    391:            if (hero.x == 0) hero.x = COLS - 1 - TERRASAVE; /* Right to left */
                    392:            else hero.x = TERRASAVE;    /* Left to right */
                    393:        }
                    394:     }
                    395:     oldrp = &rooms[rm];                /* Set the current room */
                    396:     player.t_oldpos = player.t_pos;    /* Set the current position */
                    397:     if (ISWEARING(R_AGGR) ||
                    398:        (cur_misc[WEAR_JEWEL] != NULL &&
                    399:         cur_misc[WEAR_JEWEL]->o_which == MM_JEWEL))
                    400:        aggravate();
                    401:     light(&hero);
                    402:     wmove(cw, hero.y, hero.x);
                    403:     waddch(cw, PLAYER);
                    404:
                    405:     if (level > cur_max)
                    406:        cur_max = level;
                    407:
                    408:     status(TRUE);
                    409: }
                    410:
                    411: /*
                    412:  * Pick a room that is really there
                    413:  */
                    414:
                    415: int
                    416: rnd_room(void)
                    417: {
                    418:     register int rm;
                    419:
                    420:     if (levtype != NORMLEV)
                    421:        rm = 0;
                    422:     else do
                    423:        {
                    424:            rm = rnd(MAXROOMS);
                    425:        } while (rooms[rm].r_flags & ISGONE);
                    426:     return rm;
                    427: }
                    428:
                    429: /*
                    430:  * put_things:
                    431:  *     put potions and scrolls on this level
                    432:  *     ltype: designates type of level to create
                    433:  */
                    434:
                    435: void
                    436: put_things(LEVTYPE ltype)
                    437: {
                    438:     register int i, rm, cnt;
                    439:     register struct object *cur;
                    440:     register struct linked_list *item, *exitptr;
                    441:     bool got_unique = FALSE;
                    442:     int length, width;
                    443:     coord tp, *exit;
                    444:
                    445:     /*
                    446:      * The only way to get new stuff is to go down into the dungeon.
                    447:      */
                    448:     if (level <= cur_max)
                    449:        return;
                    450:
                    451:     /*
                    452:      * There is a chance that there is a treasure room on this level
                    453:      * Increasing chance after level 9
                    454:      */
                    455:     if (ltype != MAZELEV && rnd(HARDER) < level - 8) {
                    456:        register int j;
                    457:        register struct room *rp;
                    458:
                    459:        /* Count the number of free spaces */
                    460:        i = 0;  /* 0 tries */
                    461:        do {
                    462:            rp = &rooms[rnd_room()];
                    463:            width = rp->r_max.y - 2;
                    464:            length = rp->r_max.x - 2;
                    465:        } until ((width*length >= MAXTREAS) || (i++ > MAXROOMS*4));
                    466:
                    467:        /* Mark the room as a treasure room */
                    468:        rp->r_flags |= ISTREAS;
                    469:
                    470:        /* Make all the doors secret doors */
                    471:        for (exitptr = rp->r_exit; exitptr; exitptr = next(exitptr)) {
                    472:            exit = DOORPTR(exitptr);
                    473:            move(exit->y, exit->x);
                    474:            addch(SECRETDOOR);
                    475:        }
                    476:
                    477:        /*
                    478:         * check to see if there are any monsters in room already
                    479:         */
                    480:        for (item = mlist; item != NULL; item = next(item)) {
                    481:            register struct thing *tp;
                    482:
                    483:            tp = THINGPTR(item);
                    484:            if (rp == roomin(&tp->t_pos)) {
                    485:                turn_on(*tp, ISMEAN);
                    486:                if (off(*tp, CANINWALL)) {
                    487:                    tp->t_dest = &hero;
                    488:                    turn_on(*tp, ISRUN);
                    489:                }
                    490:                if (on(*tp, ISUNIQUE))
                    491:                    got_unique = TRUE;
                    492:
                    493:                /* If it is a mimic, undisguise it */
                    494:                if (on(*tp, ISDISGUISE))
                    495:                    turn_off(*tp, ISDISGUISE);
                    496:            }
                    497:        }
                    498:
                    499:
                    500:        /* Put in the monsters and treasures */
                    501:        for (j=1; j<rp->r_max.y-1; j++)
                    502:            for (i=1; i<rp->r_max.x-1; i++) {
                    503:                coord trp;
                    504:
                    505:                trp.y = rp->r_pos.y+j;
                    506:                trp.x = rp->r_pos.x+i;
                    507:
                    508:                /* Monsters */
                    509:                if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
                    510:                    (mvwinch(mw, rp->r_pos.y+j, rp->r_pos.x+i) == ' ')) {
                    511:                    register struct thing *tp;
                    512:
                    513:                    /* Make a monster */
                    514:                    item = new_item(sizeof *tp);
                    515:                    tp = THINGPTR(item);
                    516:
                    517:                    /*
                    518:                     * Put it there and aggravate it (unless it can escape)
                    519:                     * only put one UNIQUE per treasure room at most
                    520:                     */
                    521:                    if (got_unique)
                    522:                        new_monster(item,randmonster(FALSE, TRUE),&trp,TRUE);
                    523:                    else
                    524:                        new_monster(item,randmonster(FALSE, FALSE),&trp,TRUE);
                    525:                    if (on(*tp, ISUNIQUE)) {
                    526:                        got_unique = TRUE;
                    527:                        carry_obj(tp, monsters[tp->t_index].m_carry);
                    528:                    }
                    529:                    turn_on(*tp, ISMEAN);
                    530:                    if (off(*tp, CANINWALL)) {
                    531:                        tp->t_dest = &hero;
                    532:                        turn_on(*tp, ISRUN);
                    533:                    }
                    534:
                    535:                    /* If it is a mimic, undisguise it */
                    536:                    if (on(*tp, ISDISGUISE))
                    537:                        turn_off(*tp, ISDISGUISE);
                    538:
                    539:                    if (on(*tp, HASFIRE)) {
                    540:                        register struct linked_list *fire_item;
                    541:
                    542:                        fire_item = creat_item();
                    543:                        ldata(fire_item) = (char *) tp;
                    544:                        attach(rp->r_fires, fire_item);
                    545:                        rp->r_flags |= HASFIRE;
                    546:                    }
                    547:                }
                    548:
                    549:                /* Treasures */
                    550:                if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
                    551:                    (mvinch(rp->r_pos.y+j, rp->r_pos.x+i) == FLOOR)) {
                    552:                    item = new_thing(ALL);
                    553:                    attach(lvl_obj, item);
                    554:                    cur = OBJPTR(item);
                    555:
                    556:                    mvaddch(trp.y, trp.x, cur->o_type);
                    557:                    cur->o_pos = trp;
                    558:                }
                    559:            }
                    560:     }
                    561:
                    562:     /*
                    563:      * Do MAXOBJ attempts to put things on a level
                    564:      */
                    565:     for (i = 0; i < MAXOBJ; i++)
                    566:        if (rnd(100) < 45) {
                    567:            /*
                    568:             * Pick a new object and link it in the list
                    569:             */
                    570:            item = new_thing(ALL);
                    571:            attach(lvl_obj, item);
                    572:            cur = OBJPTR(item);
                    573:            /*
                    574:             * Put it somewhere
                    575:             */
                    576:            cnt = 0;
                    577:            do {
                    578:                rm = rnd_room();
                    579:                rnd_pos(&rooms[rm], &tp);
                    580:            } until (winat(tp.y, tp.x) == FLOOR || cnt++ > 500);
                    581:            mvaddch(tp.y, tp.x, cur->o_type);
                    582:            cur->o_pos = tp;
                    583:        }
                    584: }

CVSweb