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

Annotation of early-roguelike/rogue4/passages.c, Revision 1.1.1.1

1.1       rubenllo    1: /*
                      2:  * Draw the connecting passages
                      3:  *
                      4:  * @(#)passages.c      4.8 (Berkeley) 1/27/82
                      5:  *
                      6:  * Rogue: Exploring the Dungeons of Doom
                      7:  * Copyright (C) 1980, 1981, 1982 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 "rogue.h"
                     16:
                     17: void conn(int r1, int r2);
                     18: void door(struct room *rm, coord *cp);
                     19: void passnum(void);
                     20: void numpass(int y, int x);
                     21:
                     22: /*
                     23:  * do_passages:
                     24:  *     Draw all the passages on a level.
                     25:  */
                     26: void
                     27: do_passages(void)
                     28: {
                     29:     register struct rdes *r1, *r2 = NULL;
                     30:     register int i, j;
                     31:     register int roomcount;
                     32:     static struct rdes
                     33:     {
                     34:        bool    conn[MAXROOMS];         /* possible to connect to room i? */
                     35:        bool    isconn[MAXROOMS];       /* connection been made to room i? */
                     36:        bool    ingraph;                /* this room in graph already? */
                     37:     } rdes[MAXROOMS] = {
                     38:        { { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
                     39:        { { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
                     40:        { { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
                     41:        { { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
                     42:        { { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
                     43:        { { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
                     44:        { { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
                     45:        { { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
                     46:        { { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
                     47:     };
                     48:
                     49:     /*
                     50:      * reinitialize room graph description
                     51:      */
                     52:     for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++)
                     53:     {
                     54:        for (j = 0; j < MAXROOMS; j++)
                     55:            r1->isconn[j] = FALSE;
                     56:        r1->ingraph = FALSE;
                     57:     }
                     58:
                     59:     /*
                     60:      * starting with one room, connect it to a random adjacent room and
                     61:      * then pick a new room to start with.
                     62:      */
                     63:     roomcount = 1;
                     64:     r1 = &rdes[rnd(MAXROOMS)];
                     65:     r1->ingraph = TRUE;
                     66:     do
                     67:     {
                     68:        /*
                     69:         * find a room to connect with
                     70:         */
                     71:        j = 0;
                     72:        for (i = 0; i < MAXROOMS; i++)
                     73:            if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
                     74:                r2 = &rdes[i];
                     75:        /*
                     76:         * if no adjacent rooms are outside the graph, pick a new room
                     77:         * to look from
                     78:         */
                     79:        if (j == 0)
                     80:        {
                     81:            do
                     82:                r1 = &rdes[rnd(MAXROOMS)];
                     83:            until (r1->ingraph);
                     84:        }
                     85:        /*
                     86:         * otherwise, connect new room to the graph, and draw a tunnel
                     87:         * to it
                     88:         */
                     89:        else
                     90:        {
                     91:            r2->ingraph = TRUE;
                     92:            i = r1 - rdes;
                     93:            j = r2 - rdes;
                     94:            conn(i, j);
                     95:            r1->isconn[j] = TRUE;
                     96:            r2->isconn[i] = TRUE;
                     97:            roomcount++;
                     98:        }
                     99:     } while (roomcount < MAXROOMS);
                    100:
                    101:     /*
                    102:      * attempt to add passages to the graph a random number of times so
                    103:      * that there isn't always just one unique passage through it.
                    104:      */
                    105:     for (roomcount = rnd(5); roomcount > 0; roomcount--)
                    106:     {
                    107:        r1 = &rdes[rnd(MAXROOMS)];      /* a random room to look from */
                    108:        /*
                    109:         * find an adjacent room not already connected
                    110:         */
                    111:        j = 0;
                    112:        for (i = 0; i < MAXROOMS; i++)
                    113:            if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
                    114:                r2 = &rdes[i];
                    115:        /*
                    116:         * if there is one, connect it and look for the next added
                    117:         * passage
                    118:         */
                    119:        if (j != 0)
                    120:        {
                    121:            i = r1 - rdes;
                    122:            j = r2 - rdes;
                    123:            conn(i, j);
                    124:            r1->isconn[j] = TRUE;
                    125:            r2->isconn[i] = TRUE;
                    126:        }
                    127:     }
                    128:     passnum();
                    129: }
                    130:
                    131: /*
                    132:  * conn:
                    133:  *     Draw a corridor from a room in a certain direction.
                    134:  */
                    135: void
                    136: conn(int r1, int r2)
                    137: {
                    138:     register struct room *rpf, *rpt = NULL;
                    139:     unsigned char rmt;
                    140:     register int distance = 0, turn_spot = 0, turn_distance = 0, index;
                    141:     register int rm;
                    142:     register char direc;
                    143:     coord del = {0,0}, curr, turn_delta = {0,0}, spos = {0,0}, epos = {0,0};
                    144:
                    145:     if (r1 < r2)
                    146:     {
                    147:        rm = r1;
                    148:        if (r1 + 1 == r2)
                    149:            direc = 'r';
                    150:        else
                    151:            direc = 'd';
                    152:     }
                    153:     else
                    154:     {
                    155:        rm = r2;
                    156:        if (r2 + 1 == r1)
                    157:            direc = 'r';
                    158:        else
                    159:            direc = 'd';
                    160:     }
                    161:     rpf = &rooms[rm];
                    162:     /*
                    163:      * Set up the movement variables, in two cases:
                    164:      * first drawing one down.
                    165:      */
                    166:     if (direc == 'd')
                    167:     {
                    168:        rmt = rm + 3;                           /* room # of dest */
                    169:        rpt = &rooms[rmt];                      /* room pointer of dest */
                    170:        del.x = 0;                              /* direction of move */
                    171:        del.y = 1;
                    172:        spos.x = rpf->r_pos.x;                  /* start of move */
                    173:        spos.y = rpf->r_pos.y;
                    174:        epos.x = rpt->r_pos.x;                  /* end of move */
                    175:        epos.y = rpt->r_pos.y;
                    176:        if (!(rpf->r_flags & ISGONE))           /* if not gone pick door pos */
                    177:        {
                    178:            spos.x += rnd(rpf->r_max.x - 2) + 1;
                    179:            spos.y += rpf->r_max.y - 1;
                    180:        }
                    181:        if (!(rpt->r_flags & ISGONE))
                    182:            epos.x += rnd(rpt->r_max.x - 2) + 1;
                    183:        distance = abs(spos.y - epos.y) - 1;    /* distance to move */
                    184:        turn_delta.y = 0;                       /* direction to turn */
                    185:        turn_delta.x = (spos.x < epos.x ? 1 : -1);
                    186:        turn_distance = abs(spos.x - epos.x);   /* how far to turn */
                    187:        turn_spot = rnd(distance-1) + 1;                /* where turn starts */
                    188:     }
                    189:     else if (direc == 'r')                     /* setup for moving right */
                    190:     {
                    191:        rmt = rm + 1;
                    192:        rpt = &rooms[rmt];
                    193:        del.x = 1;
                    194:        del.y = 0;
                    195:        spos.x = rpf->r_pos.x;
                    196:        spos.y = rpf->r_pos.y;
                    197:        epos.x = rpt->r_pos.x;
                    198:        epos.y = rpt->r_pos.y;
                    199:        if (!(rpf->r_flags & ISGONE))
                    200:        {
                    201:            spos.x += rpf->r_max.x-1;
                    202:            spos.y += rnd(rpf->r_max.y-2)+1;
                    203:        }
                    204:        if (!(rpt->r_flags & ISGONE))
                    205:            epos.y += rnd(rpt->r_max.y-2)+1;
                    206:        distance = abs(spos.x - epos.x) - 1;
                    207:        turn_delta.y = (spos.y < epos.y ? 1 : -1);
                    208:        turn_delta.x = 0;
                    209:        turn_distance = abs(spos.y - epos.y);
                    210:        turn_spot = rnd(distance-1) + 1;
                    211:     }
                    212: #ifdef WIZARD
                    213:     else
                    214:        debug("error in connection tables");
                    215: #endif
                    216:     /*
                    217:      * Draw in the doors on either side of the passage or just put #'s
                    218:      * if the rooms are gone.
                    219:      */
                    220:     if (!(rpf->r_flags & ISGONE))
                    221:        door(rpf, &spos);
                    222:     else
                    223:     {
                    224:        index = INDEX(spos.y, spos.x);
                    225:        _level[index] = PASSAGE;
                    226:        _flags[index] |= F_PASS;
                    227:     }
                    228:     if (!(rpt->r_flags & ISGONE))
                    229:        door(rpt, &epos);
                    230:     else
                    231:     {
                    232:        index = INDEX(epos.y, epos.x);
                    233:        _level[index] = PASSAGE;
                    234:        _flags[index] |= F_PASS;
                    235:     }
                    236:     /*
                    237:      * Get ready to move...
                    238:      */
                    239:     curr.x = spos.x;
                    240:     curr.y = spos.y;
                    241:     while (distance)
                    242:     {
                    243:        /*
                    244:         * Move to new position
                    245:         */
                    246:        curr.x += del.x;
                    247:        curr.y += del.y;
                    248:        /*
                    249:         * Check if we are at the turn place, if so do the turn
                    250:         */
                    251:        if (distance == turn_spot)
                    252:            while (turn_distance--)
                    253:            {
                    254:                index = INDEX(curr.y, curr.x);
                    255:                _level[index] = PASSAGE;
                    256:                _flags[index] |= F_PASS;
                    257:                curr.x += turn_delta.x;
                    258:                curr.y += turn_delta.y;
                    259:            }
                    260:        /*
                    261:         * Continue digging along
                    262:         */
                    263:        index = INDEX(curr.y, curr.x);
                    264:        _level[index] = PASSAGE;
                    265:        _flags[index] |= F_PASS;
                    266:        distance--;
                    267:     }
                    268:     curr.x += del.x;
                    269:     curr.y += del.y;
                    270:     if (!ce(curr, epos))
                    271:        msg("warning, connectivity problem on this level");
                    272: }
                    273:
                    274: /*
                    275:  * door:
                    276:  *     Add a door or possibly a secret door.  Also enters the door in
                    277:  *     the exits array of the room.
                    278:  */
                    279: void
                    280: door(struct room *rm, coord *cp)
                    281: {
                    282:     register int index;
                    283:
                    284:     index = INDEX(cp->y, cp->x);
                    285:     if (rnd(10) + 1 < level && rnd(5) == 0)
                    286:     {
                    287:        _level[index] = (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1) ? '-' : '|';
                    288:        _flags[index] &= ~F_REAL;
                    289:     }
                    290:     else
                    291:        _level[index] = DOOR;
                    292:     rm->r_exit[rm->r_nexits++] = *cp;
                    293: }
                    294:
                    295: #ifdef WIZARD
                    296: /*
                    297:  * add_pass:
                    298:  *     Add the passages to the current window (wizard command)
                    299:  */
                    300: void
                    301: add_pass(void)
                    302: {
                    303:     register int y, x, ch;
                    304:
                    305:     for (y = 1; y < LINES - 1; y++)
                    306:        for (x = 0; x < COLS; x++)
                    307:            if ((ch = chat(y, x)) == DOOR || ch == PASSAGE)
                    308:                mvaddch(y, x, ch);
                    309: }
                    310: #endif
                    311:
                    312: /*
                    313:  * passnum:
                    314:  *     Assign a number to each passageway
                    315:  */
                    316: static int pnum;
                    317: static bool newpnum;
                    318:
                    319: void
                    320: passnum(void)
                    321: {
                    322:     register struct room *rp;
                    323:     register int i;
                    324:
                    325:     pnum = 0;
                    326:     newpnum = FALSE;
                    327:     for (rp = passages; rp < &passages[MAXPASS]; rp++)
                    328:        rp->r_nexits = 0;
                    329:     for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
                    330:        for (i = 0; i < rp->r_nexits; i++)
                    331:        {
                    332:            newpnum++;
                    333:            numpass(rp->r_exit[i].y, rp->r_exit[i].x);
                    334:        }
                    335: }
                    336:
                    337: /*
                    338:  * numpass:
                    339:  *     Number a passageway square and its brethren
                    340:  */
                    341: void
                    342: numpass(int y, int x)
                    343: {
                    344:     register char *fp;
                    345:     register struct room *rp;
                    346:     register char ch;
                    347:
                    348:     fp = &flat(y, x);
                    349:     if (*fp & F_PNUM)
                    350:        return;
                    351:     if (newpnum)
                    352:     {
                    353:        pnum++;
                    354:        newpnum = FALSE;
                    355:     }
                    356:     /*
                    357:      * check to see if it is a door or secret door, i.e., a new exit,
                    358:      * or a numerable type of place
                    359:      */
                    360:     if ((ch = chat(y, x)) == DOOR || (!(*fp & F_REAL) && ch != FLOOR))
                    361:     {
                    362:        rp = &passages[pnum];
                    363:        rp->r_exit[rp->r_nexits].y = y;
                    364:        rp->r_exit[rp->r_nexits++].x = x;
                    365:     }
                    366:     else if (!(*fp & F_PASS))
                    367:        return;
                    368:     *fp |= pnum;
                    369:     /*
                    370:      * recurse on the surrounding places
                    371:      */
                    372:     numpass(y + 1, x);
                    373:     numpass(y - 1, x);
                    374:     numpass(y, x + 1);
                    375:     numpass(y, x - 1);
                    376: }

CVSweb