我只是在玩NetHack,因为我正在为自己编写一个简化版本。我的问题是,如何实现走廊?我已经尝试了几天了,无法提出合理的建议。

最佳答案

Nethack中的 map 生成发生在mkmap.c中。 join_map方法确定应连接哪些房间。 sp_lev.c中的dig_corridor方法进行了实际的挖掘。

兴趣线:

if (tx > xx)        dx = 1;
else if (ty > yy)   dy = 1;
else if (tx < xx)   dx = -1;
else            dy = -1;

这会将“当前X和Y”与“目标X和Y”进行比较,以确定我们最初将挖掘的方向。
while(xx != tx || yy != ty) {
    /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
    if(cct++ > 500 || (nxcor && !rn2(35)))
    return FALSE;

我们将继续努力,直到达到目标为止,但有一些异常(exception):如果“走廊数” cct为500,则我们已经走了很长一段路要放弃。如果nxcor为true,则走廊被允许走到尽头。 rn2是一个随机数生成器,因此,如果可能出现死胡同,那么在每个循环中我们都会放弃的机会很小。
    crm = &levl[xx][yy];
    if(crm->typ == btyp) {
    if(ftyp != CORR || rn2(100)) {
        crm->typ = ftyp;
        if(nxcor && !rn2(50))
            (void) mksobj_at(BOULDER, xx, yy, TRUE, FALSE);
    } else {
        crm->typ = SCORR;
    }

crm是我们当前使用的磁贴。大多数时候,我们将瓷砖制作成普通的走廊。有时,我们将图块制作成SCORR(即 secret 走廊),只有在通过搜索找到它之后才能遍历该图块。如果路径可能是死路一条,我们也会放置巨石。
    /* do we have to change direction ? */
    if(dy && dix > diy) {
    register int ddx = (xx > tx) ? -1 : 1;

    crm = &levl[xx+ddx][yy];
    if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
        dx = ddx;
        dy = 0;
        continue;
    }
    } else if(dx && diy > dix) {
    register int ddy = (yy > ty) ? -1 : 1;

    crm = &levl[xx][yy+ddy];
    if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
        dy = ddy;
        dx = 0;
        continue;
    }
    }

如果在当前位置和目标位置之间绘制的直线的“斜率​​”明显偏离45度,则我们尝试改变方向;如果我们沿着X轴移动,那么我们开始沿着Y轴移动;反之亦然。这会导致连接两个对角房间的典型的弯曲的楼梯形走廊。如果改变方向会导致我们撞到障碍物(其他房间,熔岩等),那么我们将继续保持前进的方向。

07-24 15:53