AssignRooms

This commit is contained in:
DizzyEggg
2024-11-08 14:29:12 +01:00
parent cf6e42ae19
commit 76d710229e
3 changed files with 288 additions and 485 deletions

View File

@@ -6,387 +6,6 @@
.text
thumb_func_start GetGridPositions
GetGridPositions:
push {r4-r7,lr}
mov r7, r8
push {r7}
adds r7, r0, 0
mov r8, r1
adds r5, r2, 0
adds r6, r3, 0
movs r4, 0
cmp r4, r5
bge _0804D04E
movs r0, 0x38
adds r1, r5, 0
bl __divsi3
adds r2, r7, 0
adds r1, r5, 0
_0804D044:
stm r2!, {r4}
adds r4, r0
subs r1, 0x1
cmp r1, 0
bne _0804D044
_0804D04E:
lsls r0, r5, 2
adds r0, r7
str r4, [r0]
movs r4, 0
lsls r5, r6, 2
cmp r4, r6
bge _0804D072
movs r0, 0x20
adds r1, r6, 0
bl __divsi3
mov r2, r8
adds r1, r6, 0
_0804D068:
stm r2!, {r4}
adds r4, r0
subs r1, 0x1
cmp r1, 0
bne _0804D068
_0804D072:
mov r1, r8
adds r0, r5, r1
str r4, [r0]
pop {r3}
mov r8, r3
pop {r4-r7}
pop {r0}
bx r0
thumb_func_end GetGridPositions
thumb_func_start InitDungeonGrid
InitDungeonGrid:
push {r4-r7,lr}
mov r7, r10
mov r6, r9
mov r5, r8
push {r5-r7}
sub sp, 0x8
mov r8, r0
adds r5, r1, 0
mov r9, r2
movs r2, 0
cmp r2, r5
bge _0804D144
lsrs r0, r5, 31
adds r0, r5, r0
asrs r0, 1
str r0, [sp]
movs r3, 0
_0804D0A6:
adds r0, r2, 0x1
mov r10, r0
mov r4, r9
cmp r4, 0
ble _0804D13E
ldr r6, _0804D0D8
ldrb r6, [r6]
str r6, [sp, 0x4]
lsls r0, r2, 4
subs r0, r2
lsls r0, 5
mov r4, r8
adds r1, r0, r4
movs r7, 0
movs r6, 0x1
mov r12, r6
mov r4, r9
_0804D0C8:
ldr r0, [sp, 0x4]
cmp r0, 0x1
bne _0804D0DC
ldr r6, [sp]
cmp r2, r6
blt _0804D0DC
strb r0, [r1, 0x8]
b _0804D102
.align 2, 0
_0804D0D8: .4byte gUnknown_202F1AE
_0804D0DC:
ldr r6, _0804D0FC
ldrb r0, [r6]
cmp r0, 0x2
bne _0804D100
lsls r0, r5, 1
adds r0, r5
cmp r0, 0
bge _0804D0EE
adds r0, 0x3
_0804D0EE:
asrs r0, 2
cmp r2, r0
blt _0804D100
mov r0, r12
strb r0, [r1, 0x8]
b _0804D102
.align 2, 0
_0804D0FC: .4byte gUnknown_202F1AE
_0804D100:
strb r3, [r1, 0x8]
_0804D102:
lsls r0, r2, 4
subs r0, r2
lsls r0, 5
add r0, r8
adds r0, r7, r0
mov r6, r12
strb r6, [r0, 0xA]
strb r3, [r0, 0xB]
strb r3, [r0, 0xF]
strb r3, [r0, 0xE]
strb r3, [r0, 0xC]
strb r3, [r0, 0x16]
strb r3, [r0, 0x15]
strb r3, [r0, 0x14]
strb r3, [r0, 0x13]
strb r3, [r0, 0x1A]
strb r3, [r0, 0x19]
strb r3, [r0, 0x18]
strb r3, [r0, 0x17]
strb r3, [r0, 0x9]
strb r3, [r0, 0x11]
strb r3, [r0, 0x10]
strb r3, [r0, 0x12]
strb r3, [r0, 0x1C]
strb r3, [r0, 0x1D]
adds r1, 0x20
adds r7, 0x20
subs r4, 0x1
cmp r4, 0
bne _0804D0C8
_0804D13E:
mov r2, r10
cmp r2, r5
blt _0804D0A6
_0804D144:
add sp, 0x8
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7}
pop {r0}
bx r0
thumb_func_end InitDungeonGrid
thumb_func_start AssignRooms
AssignRooms:
push {r4-r7,lr}
mov r7, r10
mov r6, r9
mov r5, r8
push {r5-r7}
sub sp, 0x114
str r0, [sp, 0x100]
mov r9, r1
mov r8, r2
adds r4, r3, 0
movs r0, 0x3
bl DungeonRandInt
adds r3, r0, 0
cmp r4, 0
bge _0804D17E
negs r4, r4
b _0804D180
_0804D178:
movs r0, 0x1
strb r0, [r4, 0xA]
b _0804D2B6
_0804D17E:
adds r4, r3
_0804D180:
movs r3, 0
mov r0, r8
mov r2, r9
muls r2, r0
cmp r3, r4
bge _0804D19A
movs r1, 0x1
_0804D18E:
mov r5, sp
adds r0, r5, r3
strb r1, [r0]
adds r3, 0x1
cmp r3, r4
blt _0804D18E
_0804D19A:
cmp r3, 0xFF
bgt _0804D1AC
movs r1, 0
_0804D1A0:
mov r6, sp
adds r0, r6, r3
strb r1, [r0]
adds r3, 0x1
cmp r3, 0xFF
ble _0804D1A0
_0804D1AC:
adds r5, r2, 0
movs r6, 0x3F
_0804D1B0:
adds r0, r5, 0
bl DungeonRandInt
adds r4, r0, 0
adds r0, r5, 0
bl DungeonRandInt
mov r1, sp
adds r2, r1, r4
ldrb r3, [r2]
adds r1, r0
ldrb r0, [r1]
strb r0, [r2]
strb r3, [r1]
subs r6, 0x1
cmp r6, 0
bge _0804D1B0
movs r3, 0
ldr r0, _0804D24C
str r3, [r0]
movs r7, 0
mov r12, r0
cmp r7, r9
bge _0804D262
_0804D1E0:
movs r5, 0
adds r4, r7, 0x1
str r4, [sp, 0x104]
cmp r5, r8
bge _0804D25C
lsls r2, r7, 4
subs r2, r7
lsls r2, 5
ldr r6, [sp, 0x100]
adds r0, r2, r6
mov r1, r9
movs r4, 0x1
ands r1, r4
str r1, [sp, 0x110]
mov r1, r9
subs r1, 0x1
adds r0, 0x20
mov r10, r0
adds r0, r6, 0
adds r0, 0x8
adds r2, r0
lsrs r0, r1, 31
adds r1, r0
asrs r1, 1
_0804D210:
ldrb r4, [r2]
cmp r4, 0
bne _0804D254
mov r6, r12
ldr r0, [r6]
cmp r0, 0x1F
ble _0804D220
strb r4, [r2, 0x2]
_0804D220:
mov r6, sp
adds r0, r6, r3
ldrb r0, [r0]
cmp r0, 0
beq _0804D250
movs r0, 0x1
strb r0, [r2, 0x2]
mov r6, r12
ldr r0, [r6]
adds r0, 0x1
str r0, [r6]
ldr r0, [sp, 0x110]
cmp r0, 0
beq _0804D252
cmp r7, r1
bne _0804D252
cmp r5, 0x1
bne _0804D252
mov r6, r10
strb r4, [r6, 0xA]
b _0804D252
.align 2, 0
_0804D24C: .4byte gUnknown_202F1CC
_0804D250:
strb r0, [r2, 0x2]
_0804D252:
adds r3, 0x1
_0804D254:
adds r2, 0x20
adds r5, 0x1
cmp r5, r8
blt _0804D210
_0804D25C:
ldr r7, [sp, 0x104]
cmp r7, r9
blt _0804D1E0
_0804D262:
mov r1, r12
ldr r0, [r1]
cmp r0, 0x1
bgt _0804D2BC
movs r1, 0
movs r2, 0
_0804D26E:
movs r7, 0
cmp r2, r9
bge _0804D2AC
movs r6, 0
_0804D276:
movs r5, 0
cmp r5, r8
bge _0804D2A4
lsls r0, r6, 5
ldr r3, [sp, 0x100]
adds r4, r0, r3
_0804D282:
ldrb r0, [r4, 0x8]
cmp r0, 0
bne _0804D29C
movs r0, 0x64
str r1, [sp, 0x108]
str r2, [sp, 0x10C]
bl DungeonRandInt
ldr r1, [sp, 0x108]
ldr r2, [sp, 0x10C]
cmp r0, 0x3B
bgt _0804D29C
b _0804D178
_0804D29C:
adds r4, 0x20
adds r5, 0x1
cmp r5, r8
blt _0804D282
_0804D2A4:
adds r6, 0xF
adds r7, 0x1
cmp r7, r9
blt _0804D276
_0804D2AC:
cmp r2, 0
bne _0804D2B6
adds r1, 0x1
cmp r1, 0xC7
ble _0804D26E
_0804D2B6:
ldr r1, _0804D2CC
movs r0, 0
strb r0, [r1]
_0804D2BC:
add sp, 0x114
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7}
pop {r0}
bx r0
.align 2, 0
_0804D2CC: .4byte gUnknown_202F1AD
thumb_func_end AssignRooms
thumb_func_start CreateRoomsAndAnchors
CreateRoomsAndAnchors:
push {r4-r7,lr}

View File

@@ -39,6 +39,13 @@
#define ARRAY_COUNT(array) (sizeof(array) / sizeof((array)[0]))
#define SWAP(a, b, temp) \
{ \
temp = a; \
a = b; \
b = temp; \
}
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))

View File

@@ -22,6 +22,7 @@ extern s16 gUnknown_202F1B0;
extern s16 gUnknown_202F1B2;
extern s32 gUnknown_202F1C8;
extern s32 gUnknown_202F1D0;
extern s32 gUnknown_202F1CC;
extern Position gUnknown_202F1D8;
struct UnkStruct_202F1B8
@@ -69,6 +70,17 @@ struct FileFixedmapPosStruct
u8 y;
};
static inline void SetTerrainNormal(Tile *tile)
{
tile->terrainType &= ~(TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY);
tile->terrainType |= TERRAIN_TYPE_NORMAL;
}
static inline u32 GetTerrain(Tile *tile)
{
return tile->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY);
}
// Some weird-ass regswap prevents the function from being matched - https://decomp.me/scratch/9SUV3
#ifdef NONMATCHING
void sub_804AFAC(void)
@@ -258,7 +270,7 @@ void sub_804AFAC(void)
if (r10) {
sub_80506F0(1, unkPtr);
}
r4 = (DungeonRandInt(100) < unkPtr->unk19);
r4 = (DungeonRandInt(100) < unkPtr->connectedToTop);
sub_804FF08(unkPtr, r4);
sub_8050438(unkPtr, r4);
sub_804FBE8();
@@ -960,15 +972,15 @@ void sub_804B534(s32 xStart, s32 yStart, s32 maxX, s32 maxY)
Tile *tile = GetTileSafe(x, y);
tile->terrainType &= ~(TERRAIN_TYPE_UNK_2);
if (tile->room == CORRIDOR_ROOM && ((tile->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL)) {
if (x > 0 && ((GetTile(x - 1, y)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL))
if (tile->room == CORRIDOR_ROOM && (GetTerrain(tile) == TERRAIN_TYPE_NORMAL)) {
if (x > 0 && (GetTerrain(GetTile(x - 1, y)) == TERRAIN_TYPE_NORMAL))
unkCount++;
if (y > 0 && ((GetTile(x, y - 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL))
if (y > 0 && (GetTerrain(GetTile(x, y - 1)) == TERRAIN_TYPE_NORMAL))
unkCount++;
if (x < DUNGEON_MAX_SIZE_X - 2 && ((GetTile(x + 1, y)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL))
if (x < DUNGEON_MAX_SIZE_X - 2 && (GetTerrain(GetTile(x + 1, y)) == TERRAIN_TYPE_NORMAL))
unkCount++;
// BUG: It should check for y and not x. Not sure if it has any effect, because this function is called only once with maxY equal to DUNGEON_MAX_SIZE_Y
if (x < DUNGEON_MAX_SIZE_Y - 2 && ((GetTile(x, y + 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL))
if (x < DUNGEON_MAX_SIZE_Y - 2 && (GetTerrain(GetTile(x, y + 1)) == TERRAIN_TYPE_NORMAL))
unkCount++;
if (unkCount > 2) {
@@ -983,30 +995,30 @@ struct GridCell
{
Position start;
Position end;
u8 unk8;
u8 unk9;
u8 unk10;
u8 unk11;
u8 unk12;
u8 unk13;
u8 unk14;
u8 unk15;
u8 unk16;
u8 unk17;
u8 unk18;
u8 unk19;
u8 unk20;
u8 unk21;
u8 unk22;
u8 unk23;
u8 unk24;
u8 unk25;
u8 unk26;
u8 unk27;
u8 unk28;
u8 unk29;
u8 unk30;
u8 unk31;
bool8 isInvalid;
bool8 unk9;
bool8 isRoom;
bool8 isConnected;
bool8 unk12;
bool8 unk13;
bool8 unk14;
bool8 unk15;
bool8 isMazeRoom;
bool8 hasBeenMerged;
bool8 isMerged;
bool8 connectedToTop;
bool8 connectedToBottom;
bool8 connectedToLeft;
bool8 connectedToRight;
bool8 unk23;
bool8 unk24;
bool8 unk25;
bool8 unk26;
bool8 unk27;
bool8 unk28;
bool8 unk29;
bool8 unk30;
bool8 unk31;
};
#define GRID_CELL_LEN 15
@@ -2315,26 +2327,26 @@ void GenerateCrossFloor(UnkDungeonGlobal_unk1C574 *unkPtr)
// Set all cells as rooms
for (x = 0; x < sizeX; x++) {
for (y = 0; y < sizeY; y++) {
grid[x][y].unk10 = TRUE;
grid[x][y].isRoom = TRUE;
}
}
// Invalidate the corners
grid[0][0].unk8 = TRUE;
grid[2][0].unk8 = TRUE;
grid[0][2].unk8 = TRUE;
grid[2][2].unk8 = TRUE;
grid[0][0].isInvalid = TRUE;
grid[2][0].isInvalid = TRUE;
grid[0][2].isInvalid = TRUE;
grid[2][2].isInvalid = TRUE;
CreateRoomsAndAnchors(grid, sizeX, sizeY, listX, listY, unkPtr->unkD);
grid[0][1].unk22 = TRUE;
grid[1][1].unk21 = TRUE;
grid[1][1].unk22 = TRUE;
grid[2][1].unk21 = TRUE;
grid[1][0].unk20 = TRUE;
grid[1][1].unk19 = TRUE;
grid[1][1].unk20 = TRUE;
grid[1][2].unk19 = TRUE;
grid[0][1].connectedToRight = TRUE;
grid[1][1].connectedToLeft = TRUE;
grid[1][1].connectedToRight = TRUE;
grid[2][1].connectedToLeft = TRUE;
grid[1][0].connectedToBottom = TRUE;
grid[1][1].connectedToTop = TRUE;
grid[1][1].connectedToBottom = TRUE;
grid[1][2].connectedToTop = TRUE;
CreateGridCellConnections(grid, sizeX, sizeY, listX, listY, TRUE);
EnsureConnectedGrid(grid, sizeX, sizeY, listX, listY);
@@ -2370,7 +2382,7 @@ void GenerateBeetleFloor(UnkDungeonGlobal_unk1C574 *unkPtr)
// Set all cells as rooms
for (x = 0; x < sizeX; x++) {
for (y = 0; y < sizeY; y++) {
grid[x][y].unk10 = TRUE;
grid[x][y].isRoom = TRUE;
}
}
@@ -2378,10 +2390,10 @@ void GenerateBeetleFloor(UnkDungeonGlobal_unk1C574 *unkPtr)
// Connect rooms in the same row together
for (y = 0; y < 3; y++) {
grid[0][y].unk22 = TRUE;
grid[1][y].unk21 = TRUE;
grid[1][y].unk22 = TRUE;
grid[2][y].unk21 = TRUE;
grid[0][y].connectedToRight = TRUE;
grid[1][y].connectedToLeft = TRUE;
grid[1][y].connectedToRight = TRUE;
grid[2][y].connectedToLeft = TRUE;
}
CreateGridCellConnections(grid, sizeX, sizeY, listX, listY, TRUE);
@@ -2413,8 +2425,7 @@ static void MergeRoomsVertically(s32 roomX, s32 room_y1, s32 room_dy, struct Gri
for (x = xStart; x < xEnd; x++) {
for (y = yStart; y < yEnd; y++) {
Tile *tile = GetTileSafe(x, y);
tile->terrainType &= ~(TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY);
tile->terrainType |= TERRAIN_TYPE_NORMAL;
SetTerrainNormal(tile);
tile->room = roomId;
}
}
@@ -2423,10 +2434,11 @@ static void MergeRoomsVertically(s32 roomX, s32 room_y1, s32 room_dy, struct Gri
grid[roomX][room_y1].end.x = xEnd;
grid[roomX][room_y1].start.y = yStart;
grid[roomX][room_y1].end.y = yEnd;
grid[roomX][room_y1 + room_dy].unk18 = TRUE;
grid[roomX][room_y1].unk18 = TRUE;
grid[roomX][room_y1 + room_dy].unk11 = FALSE;
grid[roomX][room_y1 + room_dy].unk17 = TRUE;
grid[roomX][room_y1 + room_dy].isMerged = TRUE;
grid[roomX][room_y1].isMerged = TRUE;
grid[roomX][room_y1 + room_dy].isConnected = FALSE;
grid[roomX][room_y1 + room_dy].hasBeenMerged = TRUE;
}
// GenerateOuterRoomsFloor - Generates a floor layout with a ring of rooms and nothing on the interior.
@@ -2446,14 +2458,14 @@ void GenerateOuterRoomsFloor(s32 sizeX_, s32 sizeY_, UnkDungeonGlobal_unk1C574 *
// Make all cells rooms
for (x = 0; x < sizeX; x++) {
for (y = 0; y < sizeY; y++) {
grid[x][y].unk10 = TRUE;
grid[x][y].isRoom = TRUE;
}
}
// Invalidate all interior cells
for (x = 1; x < sizeX - 1; x++) {
for (y = 1; y < sizeY - 1; y++) {
grid[x][y].unk8 = TRUE;
grid[x][y].isInvalid = TRUE;
}
}
@@ -2467,8 +2479,8 @@ void GenerateOuterRoomsFloor(s32 sizeX_, s32 sizeY_, UnkDungeonGlobal_unk1C574 *
// instead of from the top, but this does not affect the connectivity of the map.
for (x = 0; x < sizeX - 1; x++) {
if (x != 0) {
grid[x][0].unk22 = TRUE;
grid[x][sizeY-1].unk22 = TRUE;
grid[x][0].connectedToRight = TRUE;
grid[x][sizeY-1].connectedToRight = TRUE;
}
// Bug: if sizeX <= 2, this branch will never be run.
@@ -2476,23 +2488,23 @@ void GenerateOuterRoomsFloor(s32 sizeX_, s32 sizeY_, UnkDungeonGlobal_unk1C574 *
// sizeX == 1, no connections will be made between columns here.
// This results in an unconnected map for sizeX <= 2.
if (x < sizeX - 2) {
grid[x+1][0].unk21 = TRUE;
grid[x+1][sizeY-1].unk21 = TRUE;
grid[x+1][0].connectedToLeft = TRUE;
grid[x+1][sizeY-1].connectedToLeft = TRUE;
}
}
for (y = 0; y < sizeY - 1; y++) {
if (y != 0) {
grid[0][y].unk19 = TRUE;
grid[sizeX-1][y].unk19 = TRUE;
grid[0][y].connectedToTop = TRUE;
grid[sizeX-1][y].connectedToTop = TRUE;
}
// This connection ends up not being set for the bottom row, but this is fine because the other
// connection to this room is still correct. The result is that hallways here will be using the opposing end
// of the grid cell boundary for their turns compared to top/bottom hallways between other rows.
if (y < sizeY - 2) {
grid[0][y].unk20 = TRUE;
grid[sizeX-1][y].unk20 = TRUE;
grid[0][y].connectedToBottom = TRUE;
grid[sizeX-1][y].connectedToBottom = TRUE;
}
}
@@ -2565,7 +2577,7 @@ void sub_804C790(s32 x1, s32 y1, s32 x2, s32 y2, s32 a4, UnkDungeonGlobal_unk1C5
x3 = DungeonRandInt(x1);
y3 = DungeonRandInt(y1);
r10 = y3 * x1 + x3;
if (grid[x3][y3].unk10)
if (grid[x3][y3].isRoom)
break;
}
sub_8050F90(grid, x1, y1, listX, listY, r10, x2, y2);
@@ -2592,16 +2604,14 @@ void GenerateOneRoomMonsterHouseFloor(void)
grid[0][0].end.x = DUNGEON_MAX_SIZE_X - 2;
grid[0][0].start.y = 2;
grid[0][0].end.y = DUNGEON_MAX_SIZE_Y - 2;
grid[0][0].unk10 = TRUE;
grid[0][0].unk11 = TRUE;
grid[0][0].unk8 = FALSE;
grid[0][0].isRoom = TRUE;
grid[0][0].isConnected = TRUE;
grid[0][0].isInvalid = FALSE;
for (x = grid[0][0].start.x; x < grid[0][0].end.x; x++) {
for (y = grid[0][0].start.y; y < grid[0][0].end.y; y++) {
Tile *tile = GetTileSafe(x, y);
tile->terrainType &= ~(TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY);
tile->terrainType |= TERRAIN_TYPE_NORMAL;
// Unnecessary call again
SetTerrainNormal(GetTileSafe(x, y));
GetTileSafe(x, y)->room = 0;
}
}
@@ -2640,7 +2650,7 @@ void GenerateTwoRoomsWithMonsterHouseFloor(void)
s32 endX = startX + roomSizeX;
s32 endY = startY + roomSizeY;
grid[x][y].unk10 = 1;
grid[x][y].isRoom = TRUE;
grid[x][y].start.x = startX;
grid[x][y].end.x = endX;
grid[x][y].start.y = startY;
@@ -2648,10 +2658,7 @@ void GenerateTwoRoomsWithMonsterHouseFloor(void)
for (currX = startX; currX < endX; currX++) {
for (currY = startY; currY < endY; currY++) {
Tile *tile = GetTileSafe(currX, currY);
tile->terrainType &= ~(TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY);
tile->terrainType |= TERRAIN_TYPE_NORMAL;
// Unnecessary call again
SetTerrainNormal(GetTileSafe(currX, currY));
GetTileSafe(currX, currY)->room = currRoomId;
}
}
@@ -2659,8 +2666,8 @@ void GenerateTwoRoomsWithMonsterHouseFloor(void)
}
}
grid[0][0].unk22 = TRUE;
grid[1][0].unk21 = TRUE;
grid[0][0].connectedToRight = TRUE;
grid[1][0].connectedToLeft = TRUE;
CreateGridCellConnections(grid, sizeX, sizeY, listX, listY, FALSE);
GenerateMonsterHouse(grid, sizeX, sizeY, 999);
@@ -2719,7 +2726,7 @@ void GenerateExtraHallways(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s
// - connected
// - valid
// - not a maze room
if (!grid[x][y].unk10 || !grid[x][y].unk11 || grid[x][y].unk8 || grid[x][y].unk16) continue;
if (!grid[x][y].isRoom || !grid[x][y].isConnected || grid[x][y].isInvalid || grid[x][y].isMazeRoom) continue;
// Choose a random tile in the room
currX = DungeonRandRange(grid[x][y].start.x, grid[x][y].end.x);
@@ -2759,7 +2766,7 @@ void GenerateExtraHallways(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s
// Keep walking until an obstacle is encountered
while (1) {
if ((GetTile(currX, currY)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) != TERRAIN_TYPE_NORMAL)
if (GetTerrain(GetTile(currX, currY)) != TERRAIN_TYPE_NORMAL)
break;
currX += gAdjacentTileOffsets[direction].x;
@@ -2767,7 +2774,7 @@ void GenerateExtraHallways(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s
}
// Abort if we reached secondary terrain
if ((GetTile(currX, currY)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_SECONDARY)
if (GetTerrain(GetTile(currX, currY)) == TERRAIN_TYPE_SECONDARY)
continue;
// Check that the current tile is at least 2 away from the map border
@@ -2788,13 +2795,13 @@ void GenerateExtraHallways(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s
// Make sure the direction 90 degrees counterclockwise isn't an open tile
checkX = gAdjacentTileOffsets[(direction + 2) & DIRECTION_MASK_CARDINAL].x;
checkY = gAdjacentTileOffsets[(direction + 2) & DIRECTION_MASK_CARDINAL].y;
if ((GetTile(currX + checkX, currY + checkY)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL)
if (GetTerrain(GetTile(currX + checkX, currY + checkY)) == TERRAIN_TYPE_NORMAL)
continue;
// Do the same for 90 degrees clockwise (or 270 counterclockwise) and make sure it's not an open tile
checkX2 = gAdjacentTileOffsets[(direction - 2) & DIRECTION_MASK_CARDINAL].x;
checkY2 = gAdjacentTileOffsets[(direction - 2) & DIRECTION_MASK_CARDINAL].y;
if ((GetTile(currX + checkX2, currY + checkY2)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL)
if (GetTerrain(GetTile(currX + checkX2, currY + checkY2)) == TERRAIN_TYPE_NORMAL)
continue;
// Number of steps to walk in one direction before turning
@@ -2808,40 +2815,43 @@ void GenerateExtraHallways(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s
// - Reached an impassable wall
// - Would result in carving out a 2x2 square (not a hallway at that point)
if (currX <= 1 || currY <= 1 || currX >= DUNGEON_MAX_SIZE_X - 1 || currY >= DUNGEON_MAX_SIZE_Y - 1) break;
if ((GetTile(currX, currY)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL) break;
if (GetTile(currX, currY)->terrainType & TERRAIN_TYPE_IMPASSABLE_WALL) break;
if (currX <= 1 || currY <= 1 || currX >= DUNGEON_MAX_SIZE_X - 1 || currY >= DUNGEON_MAX_SIZE_Y - 1)
break;
if (GetTerrain(GetTile(currX, currY)) == TERRAIN_TYPE_NORMAL)
break;
if (GetTile(currX, currY)->terrainType & TERRAIN_TYPE_IMPASSABLE_WALL)
break;
willNotMakeSquare = TRUE;
// Check Bottom to Right
if (((GetTile(currX + 1, currY)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL) &&
((GetTile(currX + 1, currY + 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL) &&
((GetTile(currX, currY + 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL))
if ((GetTerrain(GetTile(currX + 1, currY)) == TERRAIN_TYPE_NORMAL) &&
(GetTerrain(GetTile(currX + 1, currY + 1)) == TERRAIN_TYPE_NORMAL) &&
(GetTerrain(GetTile(currX, currY + 1)) == TERRAIN_TYPE_NORMAL))
{
willNotMakeSquare = FALSE;
}
// Check Top to Right
if (((GetTile(currX + 1, currY)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL) &&
((GetTile(currX + 1, currY - 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL) &&
((GetTile(currX, currY - 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL))
if ((GetTerrain(GetTile(currX + 1, currY)) == TERRAIN_TYPE_NORMAL) &&
(GetTerrain(GetTile(currX + 1, currY - 1)) == TERRAIN_TYPE_NORMAL) &&
(GetTerrain(GetTile(currX, currY - 1)) == TERRAIN_TYPE_NORMAL))
{
willNotMakeSquare = FALSE;
}
// Check Bottom to Left
if (((GetTile(currX - 1, currY)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL) &&
((GetTile(currX - 1, currY + 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL) &&
((GetTile(currX, currY + 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL))
if ((GetTerrain(GetTile(currX - 1, currY)) == TERRAIN_TYPE_NORMAL) &&
(GetTerrain(GetTile(currX - 1, currY + 1)) == TERRAIN_TYPE_NORMAL) &&
(GetTerrain(GetTile(currX, currY + 1)) == TERRAIN_TYPE_NORMAL))
{
willNotMakeSquare = FALSE;
}
// Check Top to Left
if (((GetTile(currX - 1, currY)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL) &&
((GetTile(currX - 1, currY - 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL) &&
((GetTile(currX, currY - 1)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL))
if ((GetTerrain(GetTile(currX - 1, currY)) == TERRAIN_TYPE_NORMAL) &&
(GetTerrain(GetTile(currX - 1, currY - 1)) == TERRAIN_TYPE_NORMAL) &&
(GetTerrain(GetTile(currX, currY - 1)) == TERRAIN_TYPE_NORMAL))
{
willNotMakeSquare = FALSE;
}
@@ -2849,21 +2859,19 @@ void GenerateExtraHallways(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s
// If TRUE, make the tile open, it will not produce a 2x2 opening
// If FALSE, it will abort from neighbor checks so we don't break here
if (willNotMakeSquare) {
Tile *tile = GetTileSafe(currX, currY);
tile->terrainType &= ~(TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY);
tile->terrainType |= TERRAIN_TYPE_NORMAL;
SetTerrainNormal(GetTileSafe(currX, currY));
}
// Make sure the direction 90 degrees counterclockwise isn't an open tile
checkX = gAdjacentTileOffsets[(direction + 2) & DIRECTION_MASK_CARDINAL].x;
checkY = gAdjacentTileOffsets[(direction + 2) & DIRECTION_MASK_CARDINAL].y;
if ((GetTile(currX + checkX, currY + checkY)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL)
if (GetTerrain(GetTile(currX + checkX, currY + checkY)) == TERRAIN_TYPE_NORMAL)
break;
// Do the same for 90 degrees clockwise (or 270 counterclockwise) and make sure it's not an open tile
checkX2 = gAdjacentTileOffsets[(direction - 2) & DIRECTION_MASK_CARDINAL].x;
checkY2 = gAdjacentTileOffsets[(direction - 2) & DIRECTION_MASK_CARDINAL].y;
if ((GetTile(currX + checkX2, currY + checkY2)->terrainType & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) == TERRAIN_TYPE_NORMAL)
if (GetTerrain(GetTile(currX + checkX2, currY + checkY2)) == TERRAIN_TYPE_NORMAL)
break;
j--;
@@ -2892,4 +2900,173 @@ void GenerateExtraHallways(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s
}
}
// GetGridPositions - Determines the starting positions of grid cells based on the given floor grid dimensions
void GetGridPositions(s32 *listX, s32 *listY, s32 sizeX, s32 sizeY)
{
s32 i, sum;
for (i = 0, sum = 0; i < sizeX; i++) {
listX[i] = sum;
sum += DUNGEON_MAX_SIZE_X / sizeX;
}
listX[sizeX] = sum;
for (i = 0, sum = 0; i < sizeY; i++) {
listY[i] = sum;
sum += DUNGEON_MAX_SIZE_Y / sizeY;
}
listY[sizeY] = sum;
}
/*
* InitDungeonGrid - Initializes the default state of the dungeon grid
*
* The dungeon grid is an array of grid cells stored in column-major order
* (to give contiguous storage to cells with the same x value), with a fixed column size of 15.
*/
void InitDungeonGrid(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s32 sizeX, s32 sizeY)
{
s32 x, y;
for (x = 0; x < sizeX; x++) {
for (y = 0; y < sizeY; y++) {
if (gUnknown_202F1AE == 1 && x >= sizeX / 2) {
grid[x][y].isInvalid = TRUE;
}
else if (gUnknown_202F1AE == 2 && x >= (sizeX * 3) / 4) {
grid[x][y].isInvalid = TRUE;
}
else {
grid[x][y].isInvalid = FALSE;
}
grid[x][y].isRoom = TRUE;
grid[x][y].isConnected = FALSE;
grid[x][y].unk15 = FALSE;
grid[x][y].unk14 = FALSE;
grid[x][y].unk12 = FALSE;
grid[x][y].connectedToRight = FALSE;
grid[x][y].connectedToLeft = FALSE;
grid[x][y].connectedToBottom = FALSE;
grid[x][y].connectedToTop = FALSE;
grid[x][y].unk26 = FALSE;
grid[x][y].unk25 = FALSE;
grid[x][y].unk24 = FALSE;
grid[x][y].unk23 = FALSE;
grid[x][y].unk9 = FALSE;
grid[x][y].hasBeenMerged = FALSE;
grid[x][y].isMazeRoom = FALSE;
grid[x][y].isMerged = FALSE;
grid[x][y].unk28 = FALSE;
grid[x][y].unk29 = FALSE;
}
}
}
/*
* AssignRooms - Randomly selects a subset of grid cells to become rooms
*
* If number_of_rooms is positive, number_of_rooms + [0..2] will become rooms
* If the selected cells for rooms are invalid, less rooms will be generated.
* The number of rooms assigned will always be at least 2 and always <= MAX_ROOM_COUNT (32).
*
* Any cells which aren't marked as rooms will become hallway anchors (those single 1x1 "rooms")
* which will be connected as hallways later, to "anchor" hallway generation
*
* Primarily Modifies: grid to assign certain grid cells to have isRoom TRUE.
*/
void AssignRooms(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s32 sizeX, s32 sizeY, s32 roomsNumber)
{
bool8 randomRoomBits[256];
s32 i, nShuffles;
s32 x, y;
s32 attempts;
s32 maxRooms;
// Extra Rooms
i = DungeonRandInt(3);
// A negative # for room count requests an exact number of rooms
if (roomsNumber < 0) {
roomsNumber = -roomsNumber;
}
else {
roomsNumber += i;
}
for (i = 0; i < roomsNumber; i++) {
randomRoomBits[i] = TRUE;
}
for (; i < 256; i++) {
randomRoomBits[i] = FALSE;
}
// Shuffle around the acceptable rooms
maxRooms = sizeX * sizeY;
for (nShuffles = 0; nShuffles < 64; nShuffles++) {
bool8 temp;
s32 a = DungeonRandInt(maxRooms);
s32 b = DungeonRandInt(maxRooms);
SWAP(randomRoomBits[a], randomRoomBits[b], temp);
}
// Counter for randomRoomBits
i = 0;
gUnknown_202F1CC = 0;
for (x = 0; x < sizeX; x++) {
for (y = 0; y < sizeY; y++) {
if (grid[x][y].isInvalid)
continue;
// There are too many rooms, remove
if (gUnknown_202F1CC >= MAX_ROOM_COUNT) {
grid[x][y].isRoom = FALSE;
}
// Using the randomly shuffled bits, create or remove the room
if (randomRoomBits[i]) {
grid[x][y].isRoom = TRUE;
gUnknown_202F1CC++;
// Don't make a room at (x_mid, 1)
if (sizeX % 2 != 0 && x == (sizeX - 1) / 2 && y == 1 ) {
grid[x][y].isRoom = FALSE;
}
}
else {
grid[x][y].isRoom = FALSE;
}
i++;
}
}
// We have at least 2 rooms, we're done.
if (gUnknown_202F1CC >= 2)
return;
for (attempts = 0; attempts < 200; attempts++) {
bool8 enoughRooms = FALSE;
for (x = 0; x < sizeX; x++) {
for (y = 0; y < sizeY; y++) {
if (grid[x][y].isInvalid)
continue;
if (DungeonRandInt(100) < 60) {
grid[x][y].isRoom = TRUE;
enoughRooms = TRUE;
// This goto is needed to match, it's used to break from two nested loops.
goto LOOP_BREAK;
}
}
}
LOOP_BREAK:
if (enoughRooms)
break;
}
gUnknown_202F1AD = FALSE;
}
//