From 8ed3cb476b6fa25e85c565e0f0e4fffca52a8b2e Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Fri, 8 Jul 2022 02:44:08 +0200 Subject: [PATCH] Clean up initial room generation --- Source/levels/drlg_l1.cpp | 255 ++++++++++++---------------- Source/levels/drlg_l2.cpp | 8 +- Source/levels/drlg_l4.cpp | 339 +++++++++++++++----------------------- Source/levels/gendung.cpp | 1 + Source/levels/gendung.h | 2 + 5 files changed, 239 insertions(+), 366 deletions(-) diff --git a/Source/levels/drlg_l1.cpp b/Source/levels/drlg_l1.cpp index b7e04daae..a48b8f31f 100644 --- a/Source/levels/drlg_l1.cpp +++ b/Source/levels/drlg_l1.cpp @@ -8,6 +8,7 @@ #include "engine/load_file.hpp" #include "engine/point.hpp" #include "engine/random.hpp" +#include "engine/rectangle.hpp" #include "levels/gendung.h" #include "player.h" #include "quests.h" @@ -23,8 +24,6 @@ int UberDiabloMonsterIndex; namespace { -/** Represents a tile ID map of twice the size, repeating each tile of the original map in blocks of 4. */ -BYTE L5dungeon[80][80]; /** Marks where walls may not be added to the level */ Bitset2d Chamber; /** Specifies whether to generate a horizontal or vertical layout. */ @@ -864,28 +863,28 @@ void InitDungeonPieces() void InitDungeonFlags() { - memset(dungeon, 0, sizeof(dungeon)); + memset(dungeon, 22, sizeof(dungeon)); Protected.reset(); Chamber.reset(); } -void MapRoom(int x, int y, int width, int height) +void MapRoom(Rectangle room) { - for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i++) { - dungeon[x + i][y + j] = Tile::VWall; + for (int y = 0; y < room.size.height; y++) { + for (int x = 0; x < room.size.width; x++) { + DungeonMask.set(room.position.x + x, room.position.y + y); } } } -bool CheckRoom(int x, int y, int width, int height) +bool CheckRoom(Rectangle room) { - for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i++) { - if (i + x < 0 || i + x >= DMAXX || j + y < 0 || j + y >= DMAXY) { + for (int j = 0; j < room.size.height; j++) { + for (int i = 0; i < room.size.width; i++) { + if (i + room.position.x < 0 || i + room.position.x >= DMAXX || j + room.position.y < 0 || j + room.position.y >= DMAXY) { return false; } - if (dungeon[i + x][j + y] != 0) { + if (DungeonMask.test(i + room.position.x, j + room.position.y)) { return false; } } @@ -894,66 +893,56 @@ bool CheckRoom(int x, int y, int width, int height) return true; } -void GenerateRoom(int x, int y, int w, int h, int dir) +void GenerateRoom(Rectangle area, bool verticalLayout) { - int dirProb = GenerateRnd(4); - int num = 0; - - bool ran; - if ((dir == 1 && dirProb == 0) || (dir != 1 && dirProb != 0)) { - int cw; - int ch; - int cx1; - int cy1; - do { - cw = (GenerateRnd(5) + 2) & ~1; - ch = (GenerateRnd(5) + 2) & ~1; - cx1 = x - cw; - cy1 = h / 2 + y - ch / 2; - ran = CheckRoom(cx1 - 1, cy1 - 1, ch + 2, cw + 1); /// BUGFIX: swap args 3 and 4 ("ch+2" and "cw+1") (workaround applied below) - num++; - } while (!ran && num < 20); - - if (ran) - MapRoom(cx1, cy1, std::min(DMAXX - cx1, cw), std::min(DMAXX - cy1, ch)); - int cx2 = x + w; - bool ran2 = CheckRoom(cx2, cy1 - 1, cw + 1, ch + 2); - if (ran2) - MapRoom(cx2, cy1, cw, ch); - if (ran) - GenerateRoom(cx1, cy1, cw, ch, 1); - if (ran2) - GenerateRoom(cx2, cy1, cw, ch, 1); - return; + bool rotate = GenerateRnd(4) == 0; + verticalLayout = (!verticalLayout && rotate) || (verticalLayout && !rotate); + + bool placeRoom1; + Rectangle room1; + + for (int num = 0; num < 20; num++) { + room1.size = { (GenerateRnd(5) + 2) & ~1, (GenerateRnd(5) + 2) & ~1 }; + room1.position = area.position; + if (verticalLayout) { + room1.position += Displacement { -room1.size.width, area.size.height / 2 - room1.size.height / 2 }; + placeRoom1 = CheckRoom({ room1.position + Displacement { -1, -1 }, { room1.size.height + 2, room1.size.width + 1 } }); /// BUGFIX: swap height and width ({ room1.size.width + 1, room1.size.height + 2 }) (workaround applied below) + } else { + room1.position += Displacement { area.size.width / 2 - room1.size.width / 2, -room1.size.height }; + placeRoom1 = CheckRoom({ room1.position + Displacement { -1, -1 }, { room1.size.width + 2, room1.size.height + 1 } }); + } + if (placeRoom1) + break; } - int width; - int height; - int rx; - int ry; - do { - width = (GenerateRnd(5) + 2) & ~1; - height = (GenerateRnd(5) + 2) & ~1; - rx = w / 2 + x - width / 2; - ry = y - height; - ran = CheckRoom(rx - 1, ry - 1, width + 2, height + 1); - num++; - } while (!ran && num < 20); - - if (ran) - MapRoom(rx, ry, width, height); - int ry2 = y + h; - bool ran2 = CheckRoom(rx - 1, ry2, width + 2, height + 1); - if (ran2) - MapRoom(rx, ry2, width, height); - if (ran) - GenerateRoom(rx, ry, width, height, 0); - if (ran2) - GenerateRoom(rx, ry2, width, height, 0); + if (placeRoom1) + MapRoom({ room1.position, { std::min(DMAXX - room1.position.x, room1.size.width), std::min(DMAXX - room1.position.y, room1.size.height) } }); + + bool placeRoom2; + Rectangle room2 = room1; + if (verticalLayout) { + room2.position.x = area.position.x + area.size.width; + placeRoom2 = CheckRoom({ room2.position + Displacement { 0, -1 }, { room2.size.width + 1, room2.size.height + 2 } }); + } else { + room2.position.y = area.position.y + area.size.height; + placeRoom2 = CheckRoom({ room2.position + Displacement { -1, 0 }, { room2.size.width + 2, room2.size.height + 1 } }); + } + + if (placeRoom2) + MapRoom(room2); + if (placeRoom1) + GenerateRoom(room1, !verticalLayout); + if (placeRoom2) + GenerateRoom(room2, !verticalLayout); } +/** + * @brief Generate a boolean dungoen room layout + */ void FirstRoom() { + DungeonMask.reset(); + VerticalLayout = !FlipCoin(); HasChamber1 = FlipCoin(); HasChamber2 = FlipCoin(); @@ -962,78 +951,66 @@ void FirstRoom() if (!HasChamber1 || !HasChamber3) HasChamber2 = true; - if (VerticalLayout) { - int ys = 1; - int ye = DMAXY - 1; - - if (HasChamber1) - MapRoom(15, 1, 10, 10); - else - ys = 18; + Rectangle chamber1 { { 15, 15 }, { 10, 10 } }; + Rectangle chamber2 { { 15, 15 }, { 10, 10 } }; + Rectangle chamber3 { { 15, 15 }, { 10, 10 } }; + Rectangle hallway { { 1, 1 }, { DMAXX - 2, DMAXY - 2 } }; - if (HasChamber2) - MapRoom(15, 15, 10, 10); - if (HasChamber3) - MapRoom(15, 29, 10, 10); - else - ye = 22; - - for (int y = ys; y < ye; y++) { - dungeon[17][y] = Tile::VWall; - dungeon[18][y] = Tile::VWall; - dungeon[19][y] = Tile::VWall; - dungeon[20][y] = Tile::VWall; - dungeon[21][y] = Tile::VWall; - dungeon[22][y] = Tile::VWall; + if (VerticalLayout) { + chamber1.position.y = 1; + chamber3.position.y = 29; + hallway.position.x = 17; + hallway.size.width = 6; + + if (!HasChamber1) { + hallway.position.y += 17; + hallway.size.height -= 17; } - if (HasChamber1) - GenerateRoom(15, 1, 10, 10, 0); - if (HasChamber2) - GenerateRoom(15, 15, 10, 10, 0); - if (HasChamber3) - GenerateRoom(15, 29, 10, 10, 0); + if (!HasChamber3) + hallway.size.height -= 16; } else { - int xs = 1; - int xe = DMAXX - 1; - - if (HasChamber1) - MapRoom(1, 15, 10, 10); - else - xs = 18; - - if (HasChamber2) - MapRoom(15, 15, 10, 10); - if (HasChamber3) - MapRoom(29, 15, 10, 10); - else - xe = 22; - - for (int x = xs; x < xe; x++) { - dungeon[x][17] = Tile::VWall; - dungeon[x][18] = Tile::VWall; - dungeon[x][19] = Tile::VWall; - dungeon[x][20] = Tile::VWall; - dungeon[x][21] = Tile::VWall; - dungeon[x][22] = Tile::VWall; + chamber1.position.x = 1; + chamber3.position.x = 29; + hallway.position.y = 17; + hallway.size.height = 6; + + if (!HasChamber1) { + hallway.position.x += 17; + hallway.size.width -= 17; } - if (HasChamber1) - GenerateRoom(1, 15, 10, 10, 1); - if (HasChamber2) - GenerateRoom(15, 15, 10, 10, 1); - if (HasChamber3) - GenerateRoom(29, 15, 10, 10, 1); + if (!HasChamber3) + hallway.size.width -= 16; } + + if (HasChamber1) + MapRoom(chamber1); + if (HasChamber2) + MapRoom(chamber2); + if (HasChamber3) + MapRoom(chamber3); + + MapRoom(hallway); + + if (HasChamber1) + GenerateRoom(chamber1, VerticalLayout); + if (HasChamber2) + GenerateRoom(chamber2, VerticalLayout); + if (HasChamber3) + GenerateRoom(chamber3, VerticalLayout); } +/** + * @brief Find the number of mega tiles used by layout + */ int FindArea() { int rv = 0; for (int j = 0; j < DMAXY; j++) { for (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert) - if (dungeon[i][j] == Tile::VWall) + if (DungeonMask.test(i, j)) rv++; } } @@ -1041,36 +1018,11 @@ int FindArea() return rv; } -void MakeDungeon() -{ - for (int j = 0; j < DMAXY; j++) { - for (int i = 0; i < DMAXX; i++) { - int i2 = i * 2; - int j2 = j * 2; - L5dungeon[i2][j2] = dungeon[i][j]; - L5dungeon[i2][j2 + 1] = dungeon[i][j]; - L5dungeon[i2 + 1][j2] = dungeon[i][j]; - L5dungeon[i2 + 1][j2 + 1] = dungeon[i][j]; - } - } -} - void MakeDmt() { - for (int j = 0; j < DMAXY; j++) { - for (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert) - dungeon[i][j] = 22; - } - } - - int dmty = 1; - for (int j = 0; dmty <= 77; j++, dmty += 2) { - int dmtx = 1; - for (int i = 0; dmtx <= 77; i++, dmtx += 2) { - int val = 8 * L5dungeon[dmtx + 1][dmty + 1] - + 4 * L5dungeon[dmtx][dmty + 1] - + 2 * L5dungeon[dmtx + 1][dmty] - + L5dungeon[dmtx][dmty]; + for (int j = 0; j < DMAXY - 1; j++) { + for (int i = 0; i < DMAXX - 1; i++) { + int val = (DungeonMask.test(i + 1, j + 1) << 3) | (DungeonMask.test(i, j + 1) << 2) | (DungeonMask.test(i + 1, j) << 1) | DungeonMask.test(i, j); dungeon[i][j] = L5ConvTbl[val]; } } @@ -1916,11 +1868,10 @@ void GenerateLevel(lvl_entry entry) DRLG_InitTrans(); do { - InitDungeonFlags(); FirstRoom(); } while (FindArea() < minarea); - MakeDungeon(); + InitDungeonFlags(); MakeDmt(); FillChambers(); FixTilesPatterns(); diff --git a/Source/levels/drlg_l2.cpp b/Source/levels/drlg_l2.cpp index b73976076..b2ffe643c 100644 --- a/Source/levels/drlg_l2.cpp +++ b/Source/levels/drlg_l2.cpp @@ -1643,12 +1643,8 @@ void InitDungeonPieces() void InitDungeonFlags() { - for (int j = 0; j < DMAXY; j++) { - for (int i = 0; i < DMAXX; i++) { - predungeon[i][j] = 32; - Protected.reset(i, j); - } - } + Protected.reset(); + memset(predungeon, 32, sizeof(predungeon)); } void MapRoom(int x1, int y1, int x2, int y2) diff --git a/Source/levels/drlg_l4.cpp b/Source/levels/drlg_l4.cpp index cc32045e4..f73a56c39 100644 --- a/Source/levels/drlg_l4.cpp +++ b/Source/levels/drlg_l4.cpp @@ -23,9 +23,6 @@ namespace { bool hallok[20]; Point L4Hold; -BYTE L4dungeon[80][80]; -BYTE dung[20][20]; -// int dword_52A4DC; /** * A lookup table for the 16 possible patterns of a 2x2 area, @@ -170,38 +167,32 @@ void LoadQuestSetPieces() void InitDungeonFlags() { - memset(dung, 0, sizeof(dung)); - memset(L4dungeon, 0, sizeof(L4dungeon)); - - for (int j = 0; j < DMAXY; j++) { - for (int i = 0; i < DMAXX; i++) { - dungeon[i][j] = 30; - Protected.reset(i, j); - } - } + DungeonMask.reset(); + Protected.reset(); + memset(dungeon, 30, sizeof(dungeon)); } -void MapRoom(int x, int y, int width, int height) +void MapRoom(Rectangle room) { - for (int j = 0; j < height && j + y < 20; j++) { - for (int i = 0; i < width && i + x < 20; i++) { - dung[i + x][j + y] = 1; + for (int y = 0; y < room.size.height && y + room.position.y < 20; y++) { + for (int x = 0; x < room.size.width && x + room.position.x < 20; x++) { + DungeonMask.set(room.position.x + x, room.position.y + y); } } } -bool CheckRoom(int x, int y, int width, int height) +bool CheckRoom(Rectangle room) { - if (x <= 0 || y <= 0) { + if (room.position.x <= 0 || room.position.y <= 0) { return false; } - for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i++) { - if (i + x < 0 || i + x >= 20 || j + y < 0 || j + y >= 20) { + for (int y = 0; y < room.size.height; y++) { + for (int x = 0; x < room.size.width; x++) { + if (x + room.position.x < 0 || x + room.position.x >= DMAXX / 2 || y + room.position.y < 0 || y + room.position.y >= DMAXY / 2) { return false; } - if (dung[i + x][j + y] != 0) { + if (DungeonMask.test(room.position.x + x, room.position.y + y)) { return false; } } @@ -210,158 +201,101 @@ bool CheckRoom(int x, int y, int width, int height) return true; } -void GenerateRoom(int x, int y, int w, int h, int dir) +void GenerateRoom(Rectangle area, bool verticalLayout) { - int dirProb = GenerateRnd(4); - int num = 0; - - bool ran; - if ((dir == 1 && dirProb == 0) || (dir != 1 && dirProb != 0)) { - int cw; - int ch; - int cx1; - int cy1; - do { - cw = (GenerateRnd(5) + 2) & ~1; - ch = (GenerateRnd(5) + 2) & ~1; - cx1 = x - cw; - cy1 = h / 2 + y - ch / 2; - ran = CheckRoom(cx1 - 1, cy1 - 1, ch + 2, cw + 1); /// BUGFIX: swap args 3 and 4 ("ch+2" and "cw+1") - num++; - } while (!ran && num < 20); - - if (ran) - MapRoom(cx1, cy1, cw, ch); - int cx2 = x + w; - bool ran2 = CheckRoom(cx2, cy1 - 1, cw + 1, ch + 2); - if (ran2) - MapRoom(cx2, cy1, cw, ch); - if (ran) - GenerateRoom(cx1, cy1, cw, ch, 1); - if (ran2) - GenerateRoom(cx2, cy1, cw, ch, 1); - return; - } - - int width; - int height; - int rx; - int ry; - do { - width = (GenerateRnd(5) + 2) & ~1; - height = (GenerateRnd(5) + 2) & ~1; - rx = w / 2 + x - width / 2; - ry = y - height; - ran = CheckRoom(rx - 1, ry - 1, width + 2, height + 1); - num++; - } while (!ran && num < 20); - - if (ran) - MapRoom(rx, ry, width, height); - int ry2 = y + h; - bool ran2 = CheckRoom(rx - 1, ry2, width + 2, height + 1); - if (ran2) - MapRoom(rx, ry2, width, height); - if (ran) - GenerateRoom(rx, ry, width, height, 0); - if (ran2) - GenerateRoom(rx, ry2, width, height, 0); + bool rotate = GenerateRnd(4) != 0; + verticalLayout = (!verticalLayout && rotate) || (verticalLayout && !rotate); + + bool placeRoom1; + Rectangle room1; + + for (int num = 0; num < 20; num++) { + room1.size = { (GenerateRnd(5) + 2) & ~1, (GenerateRnd(5) + 2) & ~1 }; + room1.position = area.position; + if (verticalLayout) { + room1.position += Displacement { -room1.size.width, area.size.height / 2 - room1.size.height / 2 }; + placeRoom1 = CheckRoom({ room1.position + Displacement { -1, -1 }, { room1.size.height + 2, room1.size.width + 1 } }); /// BUGFIX: swap height and width ({ room1.size.width + 1, room1.size.height + 2 }) (workaround applied below) + } else { + room1.position += Displacement { area.size.width / 2 - room1.size.width / 2, -room1.size.height }; + placeRoom1 = CheckRoom({ room1.position + Displacement { -1, -1 }, { room1.size.width + 2, room1.size.height + 1 } }); + } + if (placeRoom1) + break; + } + + if (placeRoom1) + MapRoom({ room1.position, { std::min(DMAXX - room1.position.x, room1.size.width), std::min(DMAXX - room1.position.y, room1.size.height) } }); + + bool placeRoom2; + Rectangle room2 = room1; + if (verticalLayout) { + room2.position.x = area.position.x + area.size.width; + placeRoom2 = CheckRoom({ room2.position + Displacement { 0, -1 }, { room2.size.width + 1, room2.size.height + 2 } }); + } else { + room2.position.y = area.position.y + area.size.height; + placeRoom2 = CheckRoom({ room2.position + Displacement { -1, 0 }, { room2.size.width + 2, room2.size.height + 1 } }); + } + + if (placeRoom2) + MapRoom(room2); + if (placeRoom1) + GenerateRoom(room1, verticalLayout); + if (placeRoom2) + GenerateRoom(room2, verticalLayout); } void FirstRoom() { - int w = 14; - int h = 14; + Rectangle room { { 0, 0 }, { 14, 14 } }; if (currlevel != 16) { if (currlevel == Quests[Q_WARLORD]._qlevel && Quests[Q_WARLORD]._qactive != QUEST_NOTAVAIL) { assert(!gbIsMultiplayer); - w = 11; - h = 11; + room.size = { 11, 11 }; } else if (currlevel == Quests[Q_BETRAYER]._qlevel && gbIsMultiplayer) { - w = 11; - h = 11; + room.size = { 11, 11 }; } else { - w = GenerateRnd(5) + 2; - h = GenerateRnd(5) + 2; + room.size = { GenerateRnd(5) + 2, GenerateRnd(5) + 2 }; } } - int xmin = (20 - w) / 2; - int xmax = 19 - w; - int x = GenerateRnd(xmax - xmin + 1) + xmin; - - int ymin = (20 - h) / 2; - int ymax = 19 - h; - int y = GenerateRnd(ymax - ymin + 1) + ymin; + int xmin = (DMAXX / 2 - room.size.width) / 2; + int xmax = DMAXX / 2 - 1 - room.size.width; + int ymin = (DMAXY / 2 - room.size.height) / 2; + int ymax = DMAXY / 2 - 1 - room.size.height; + room.position = { GenerateRnd(xmax - xmin + 1) + xmin, GenerateRnd(ymax - ymin + 1) + ymin }; if (currlevel == 16) { - L4Hold = { x, y }; + L4Hold = room.position; } if (Quests[Q_WARLORD].IsAvailable() || (currlevel == Quests[Q_BETRAYER]._qlevel && gbIsMultiplayer)) { - SetPieceRoom = { { x + 1, y + 1 }, { w + 1, h + 1 } }; + SetPieceRoom = { room.position + Displacement { 1, 1 }, { room.size.width + 1, room.size.height + 1 } }; } else { SetPieceRoom = {}; } - MapRoom(x, y, w, h); - GenerateRoom(x, y, w, h, GenerateRnd(2)); + MapRoom(room); + GenerateRoom(room, GenerateRnd(2)); } void MakeDungeon() { - for (int j = 0; j < 20; j++) { - for (int i = 0; i < 20; i++) { - int k = i * 2; - int l = j * 2; - L4dungeon[k][l] = dung[i][j]; - L4dungeon[k][l + 1] = dung[i][j]; - L4dungeon[k + 1][l] = dung[i][j]; - L4dungeon[k + 1][l + 1] = dung[i][j]; - } - } - for (int j = 0; j < 20; j++) { - for (int i = 0; i < 20; i++) { - int k = i * 2; - int l = j * 2; - L4dungeon[k][l + 40] = dung[i][19 - j]; - L4dungeon[k][l + 41] = dung[i][19 - j]; - L4dungeon[k + 1][l + 40] = dung[i][19 - j]; - L4dungeon[k + 1][l + 41] = dung[i][19 - j]; - } - } - for (int j = 0; j < 20; j++) { - for (int i = 0; i < 20; i++) { - int k = i * 2; - int l = j * 2; - L4dungeon[k + 40][l] = dung[19 - i][j]; - L4dungeon[k + 40][l + 1] = dung[19 - i][j]; - L4dungeon[k + 41][l] = dung[19 - i][j]; - L4dungeon[k + 41][l + 1] = dung[19 - i][j]; - } - } - for (int j = 0; j < 20; j++) { - for (int i = 0; i < 20; i++) { - int k = i * 2; - int l = j * 2; - L4dungeon[k + 40][l + 40] = dung[19 - i][19 - j]; - L4dungeon[k + 40][l + 41] = dung[19 - i][19 - j]; - L4dungeon[k + 41][l + 40] = dung[19 - i][19 - j]; - L4dungeon[k + 41][l + 41] = dung[19 - i][19 - j]; + for (int y = 0; y < DMAXY / 2; y++) { + for (int x = 0; x < DMAXX / 2; x++) { + if (DungeonMask.test(x, y)) { + DungeonMask.set(x, DMAXY - 1 - y); + DungeonMask.set(DMAXX - 1 - x, y); + DungeonMask.set(DMAXX - 1 - x, DMAXY - 1 - y); + } } } } void MakeDmt() { - int dmty = 1; - for (int j = 0; dmty <= 77; j++, dmty += 2) { - int dmtx = 1; - for (int i = 0; dmtx <= 77; i++, dmtx += 2) { - int val = 8 * L4dungeon[dmtx + 1][dmty + 1] - + 4 * L4dungeon[dmtx][dmty + 1] - + 2 * L4dungeon[dmtx + 1][dmty] - + L4dungeon[dmtx][dmty]; - dungeon[i][j] = L4ConvTbl[val]; + for (int y = 0; y < DMAXY - 1; y++) { + for (int x = 0; x < DMAXX - 1; x++) { + int val = (DungeonMask.test(x + 1, y + 1) << 3) | (DungeonMask.test(x, y + 1) << 2) | (DungeonMask.test(x + 1, y) << 1) | DungeonMask.test(x, y); + dungeon[x][y] = L4ConvTbl[val]; } } } @@ -912,96 +846,85 @@ void Substitution() void UShape() { - for (int j = 19; j >= 0; j--) { - for (int i = 19; i >= 0; i--) { - if (dung[i][j] != 1) { - hallok[j] = false; - } - if (dung[i][j] == 1) { - // BUGFIX: check that i + 1 < 20 and j + 1 < 20 (fixed) - if (i + 1 < 20 && j + 1 < 20 - && dung[i][j + 1] == 1 && dung[i + 1][j + 1] == 0) { - hallok[j] = true; - } else { - hallok[j] = false; - } - i = 0; + for (int y = DMAXY / 2 - 1; y >= 0; y--) { + for (int x = DMAXX / 2 - 1; x >= 0; x--) { + if (!DungeonMask.test(x, y)) { + hallok[y] = false; + } else { + hallok[y] = x + 1 < DMAXX / 2 && y + 1 < DMAXY / 2 && DungeonMask.test(x, y + 1) && !DungeonMask.test(x + 1, y + 1); + x = 0; } } } - int rv = GenerateRnd(19) + 1; + int ry = GenerateRnd(DMAXY / 2 - 1) + 1; do { - if (hallok[rv]) { - for (int i = 19; i >= 0; i--) { - if (dung[i][rv] == 1) { - i = -1; - rv = 0; + if (hallok[ry]) { + for (int x = DMAXX / 2 - 1; x >= 0; x--) { + if (DungeonMask.test(x, ry)) { + x = -1; + ry = 0; } else { - dung[i][rv] = 1; - dung[i][rv + 1] = 1; + DungeonMask.set(x, ry); + DungeonMask.set(x, ry + 1); } } } else { - rv++; - if (rv == 20) { - rv = 1; + ry++; + if (ry == DMAXY / 2) { + ry = 1; } } - } while (rv != 0); + } while (ry != 0); - for (int i = 19; i >= 0; i--) { - for (int j = 19; j >= 0; j--) { - if (dung[i][j] != 1) { - hallok[i] = false; - } - if (dung[i][j] == 1) { - // BUGFIX: check that i + 1 < 20 and j + 1 < 20 (fixed) - if (i + 1 < 20 && j + 1 < 20 - && dung[i + 1][j] == 1 && dung[i + 1][j + 1] == 0) { - hallok[i] = true; - } else { - hallok[i] = false; - } - j = 0; + for (int x = DMAXX / 2 - 1; x >= 0; x--) { + for (int y = DMAXY / 2 - 1; y >= 0; y--) { + if (!DungeonMask.test(x, y)) { + hallok[x] = false; + } else { + hallok[x] = x + 1 < DMAXX / 2 && y + 1 < DMAXY / 2 && DungeonMask.test(x + 1, y) && !DungeonMask.test(x + 1, y + 1); + y = 0; } } } - rv = GenerateRnd(19) + 1; + int rx = GenerateRnd(DMAXX / 2 - 1) + 1; do { - if (hallok[rv]) { - for (int j = 19; j >= 0; j--) { - if (dung[rv][j] == 1) { - j = -1; - rv = 0; + if (hallok[rx]) { + for (int y = DMAXY / 2 - 1; y >= 0; y--) { + if (DungeonMask.test(rx, y)) { + y = -1; + rx = 0; } else { - dung[rv][j] = 1; - dung[rv + 1][j] = 1; + DungeonMask.set(rx, y); + DungeonMask.set(rx + 1, y); } } } else { - rv++; - if (rv == 20) { - rv = 1; + rx++; + if (rx == DMAXX / 2) { + rx = 1; } } - } while (rv != 0); + } while (rx != 0); } -int GetArea() +/** + * @brief Find the number of mega tiles used by layout + */ +int FindArea() { - int rv = 0; + int area = 0; - for (int j = 0; j < 20; j++) { - for (int i = 0; i < 20; i++) { // NOLINT(modernize-loop-convert) - if (dung[i][j] == 1) { - rv++; + for (int y = 0; y < DMAXY / 2; y++) { + for (int x = 0; x < DMAXX / 2; x++) { // NOLINT(modernize-loop-convert) + if (DungeonMask.test(x, y)) { + area++; } } } - return rv; + return area * 4; } void ProtectQuads() @@ -1128,11 +1051,11 @@ void FixCornerTiles() void FixRim() { - for (int i = 0; i < 20; i++) { // NOLINT(modernize-loop-convert) - dung[i][0] = 0; + for (int x = 0; x < DMAXX / 2; x++) { // NOLINT(modernize-loop-convert) + DungeonMask.reset(x, 0); } - for (int j = 0; j < 20; j++) { - dung[0][j] = 0; + for (int y = 0; y < DMAXY / 2; y++) { + DungeonMask.reset(0, y); } } @@ -1201,12 +1124,12 @@ void GenerateLevel(lvl_entry entry) while (true) { DRLG_InitTrans(); - constexpr int Minarea = 173; + constexpr int Minarea = 692; do { InitDungeonFlags(); FirstRoom(); FixRim(); - } while (GetArea() < Minarea); + } while (FindArea() < Minarea); UShape(); MakeDungeon(); diff --git a/Source/levels/gendung.cpp b/Source/levels/gendung.cpp index 14e3a7fdb..a722c2b22 100644 --- a/Source/levels/gendung.cpp +++ b/Source/levels/gendung.cpp @@ -15,6 +15,7 @@ namespace devilution { +Bitset2d DungeonMask; uint8_t dungeon[DMAXX][DMAXY]; uint8_t pdungeon[DMAXX][DMAXY]; Bitset2d Protected; diff --git a/Source/levels/gendung.h b/Source/levels/gendung.h index 27ad50946..85cca8e18 100644 --- a/Source/levels/gendung.h +++ b/Source/levels/gendung.h @@ -137,6 +137,8 @@ struct ShadowStruct { uint8_t nv3; }; +/** Reprecents what tiles are being utilized in the generated map. */ +extern Bitset2d DungeonMask; /** Contains the tile IDs of the map. */ extern DVL_API_FOR_TEST uint8_t dungeon[DMAXX][DMAXY]; /** Contains a backup of the tile IDs of the map. */