Browse Source

Clean up initial room generation

pull/4920/head
Anders Jenbo 4 years ago
parent
commit
8ed3cb476b
  1. 255
      Source/levels/drlg_l1.cpp
  2. 8
      Source/levels/drlg_l2.cpp
  3. 339
      Source/levels/drlg_l4.cpp
  4. 1
      Source/levels/gendung.cpp
  5. 2
      Source/levels/gendung.h

255
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<DMAXX, DMAXY> 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();

8
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)

339
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();

1
Source/levels/gendung.cpp

@ -15,6 +15,7 @@
namespace devilution {
Bitset2d<DMAXX, DMAXY> DungeonMask;
uint8_t dungeon[DMAXX][DMAXY];
uint8_t pdungeon[DMAXX][DMAXY];
Bitset2d<DMAXX, DMAXY> Protected;

2
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<DMAXX, DMAXY> 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. */

Loading…
Cancel
Save