Yeah, I've looked at the code. (And wish it had a moveable setup to load new creatures and stuff from json files because it really does have that setup in the way it loads monsters, but that's besides the point
Code: Select all
void liquidType(short *deep, short *shallow, short *shallowWidth) {
short randMin, randMax, rand;
randMin = (rogue.depthLevel < MINIMUM_LAVA_LEVEL ? 1 : 0);
randMax = (rogue.depthLevel < MINIMUM_BRIMSTONE_LEVEL ? 2 : 3);
rand = rand_range(randMin, randMax);
if (rogue.depthLevel == DEEPEST_LEVEL) {
rand = 1;
}
switch(rand) {
case 0:
*deep = LAVA;
*shallow = NOTHING;
*shallowWidth = 0;
break;
case 1:
*deep = DEEP_WATER;
*shallow = SHALLOW_WATER;
*shallowWidth = 2;
break;
case 2:
*deep = CHASM;
*shallow = CHASM_EDGE;
*shallowWidth = 1;
break;
case 3:
*deep = INERT_BRIMSTONE;
*shallow = OBSIDIAN;
*shallowWidth = 2;
break;
}
}
// Fills a lake marked in unfilledLakeMap with the specified liquid type, scanning outward to reach other lakes within scanWidth.
// Any wreath of shallow liquid must be done elsewhere.
void fillLake(short x, short y, short liquid, short scanWidth, char wreathMap[DCOLS][DROWS], short **unfilledLakeMap) {
short i, j;
for (i = x - scanWidth; i <= x + scanWidth; i++) {
for (j = y - scanWidth; j <= y + scanWidth; j++) {
if (coordinatesAreInMap(i, j) && unfilledLakeMap[i][j]) {
unfilledLakeMap[i][j] = false;
pmap[i][j].layers[LIQUID] = liquid;
wreathMap[i][j] = 1;
fillLake(i, j, liquid, scanWidth, wreathMap, unfilledLakeMap); // recursive
}
}
}
}
void lakeFloodFill(short x, short y, short **floodMap, short **grid, short **lakeMap, short dungeonToGridX, short dungeonToGridY) {
short newX, newY;
enum directions dir;
floodMap[x][y] = true;
for (dir=0; dir<4; dir++) {
newX = x + nbDirs[dir][0];
newY = y + nbDirs[dir][1];
if (coordinatesAreInMap(newX, newY)
&& !floodMap[newX][newY]
&& (!cellHasTerrainFlag(newX, newY, T_PATHING_BLOCKER) || cellHasTMFlag(newX, newY, TM_CONNECTS_LEVEL))
&& !lakeMap[newX][newY]
&& (!coordinatesAreInMap(newX+dungeonToGridX, newY+dungeonToGridY) || !grid[newX+dungeonToGridX][newY+dungeonToGridY])) {
lakeFloodFill(newX, newY, floodMap, grid, lakeMap, dungeonToGridX, dungeonToGridY);
}
}
}
boolean lakeDisruptsPassability(short **grid, short **lakeMap, short dungeonToGridX, short dungeonToGridY) {
boolean result;
short i, j, x, y;
short **floodMap;
floodMap = allocGrid();
fillGrid(floodMap, 0);
x = y = -1;
// Get starting location for the fill.
for (i=0; i<DCOLS && x == -1; i++) {
for (j=0; j<DROWS && x == -1; j++) {
if (!cellHasTerrainFlag(i, j, T_PATHING_BLOCKER)
&& !lakeMap[i][j]
&& (!coordinatesAreInMap(i+dungeonToGridX, j+dungeonToGridY) || !grid[i+dungeonToGridX][j+dungeonToGridY])) {
x = i;
y = j;
}
}
}
brogueAssert(x != -1);
// Do the flood fill.
lakeFloodFill(x, y, floodMap, grid, lakeMap, dungeonToGridX, dungeonToGridY);
// See if any dry tiles weren't reached by the flood fill.
result = false;
for (i=0; i<DCOLS && result == false; i++) {
for (j=0; j<DROWS && result == false; j++) {
if (!cellHasTerrainFlag(i, j, T_PATHING_BLOCKER)
&& !lakeMap[i][j]
&& !floodMap[i][j]
&& (!coordinatesAreInMap(i+dungeonToGridX, j+dungeonToGridY) || !grid[i+dungeonToGridX][j+dungeonToGridY])) {
// if (D_INSPECT_LEVELGEN) {
// dumpLevelToScreen();
// hiliteGrid(lakeMap, &darkBlue, 75);
// hiliteGrid(floodMap, &white, 20);
// plotCharWithColor('X', mapToWindowX(i), mapToWindowY(j), &black, &red);
// temporaryMessage("Failed here.", REQUIRE_ACKNOWLEDGMENT);
// }
result = true;
}
}
}
freeGrid(floodMap);
return result;
}
void designLakes(short **lakeMap) {
short i, j, k;
short x, y;
short lakeMaxHeight, lakeMaxWidth;
short lakeX, lakeY, lakeWidth, lakeHeight;
short **grid; // Holds the current lake.
grid = allocGrid();
fillGrid(lakeMap, 0);
for (lakeMaxHeight = 15, lakeMaxWidth = 30; lakeMaxHeight >=10; lakeMaxHeight--, lakeMaxWidth -= 2) { // lake generations
fillGrid(grid, 0);
createBlobOnGrid(grid, &lakeX, &lakeY, &lakeWidth, &lakeHeight, 5, 4, 4, lakeMaxWidth, lakeMaxHeight, 55, "ffffftttt", "ffffttttt");
// if (D_INSPECT_LEVELGEN) {
// colorOverDungeon(&darkGray);
// hiliteGrid(grid, &white, 100);
// temporaryMessage("Generated a lake.", REQUIRE_ACKNOWLEDGMENT);
// }
for (k=0; k<20; k++) { // placement attempts
// propose a position for the top-left of the grid in the dungeon
x = rand_range(1 - lakeX, DCOLS - lakeWidth - lakeX - 2);
y = rand_range(1 - lakeY, DROWS - lakeHeight - lakeY - 2);
if (!lakeDisruptsPassability(grid, lakeMap, -x, -y)) { // level with lake is completely connected
//printf("Placed a lake!");
// copy in lake
for (i = 0; i < lakeWidth; i++) {
for (j = 0; j < lakeHeight; j++) {
if (grid[i + lakeX][j + lakeY]) {
lakeMap[i + lakeX + x][j + lakeY + y] = true;
pmap[i + lakeX + x][j + lakeY + y].layers[DUNGEON] = FLOOR;
}
}
}
if (D_INSPECT_LEVELGEN) {
dumpLevelToScreen();
hiliteGrid(lakeMap, &white, 50);
temporaryMessage("Added a lake location.", REQUIRE_ACKNOWLEDGMENT);
}
break;
}
}
}
freeGrid(grid);
}
void createWreath(short shallowLiquid, short wreathWidth, char wreathMap[DCOLS][DROWS]) {
short i, j, k, l;
for (i=0; i<DCOLS; i++) {
for (j=0; j<DROWS; j++) {
if (wreathMap[i][j]) {
for (k = i-wreathWidth; k<= i+wreathWidth; k++) {
for (l = j-wreathWidth; l <= j+wreathWidth; l++) {
if (coordinatesAreInMap(k, l) && pmap[k][l].layers[LIQUID] == NOTHING
&& (i-k)*(i-k) + (j-l)*(j-l) <= wreathWidth*wreathWidth) {
pmap[k][l].layers[LIQUID] = shallowLiquid;
if (pmap[k][l].layers[DUNGEON] == DOOR) {
pmap[k][l].layers[DUNGEON] = FLOOR;
}
}
}
}
}
}
}
}
void fillLakes(short **lakeMap) {
short deepLiquid = CRYSTAL_WALL, shallowLiquid = CRYSTAL_WALL, shallowLiquidWidth = 0;
char wreathMap[DCOLS][DROWS];
short i, j;
for (i=0; i<DCOLS; i++) {
for (j=0; j<DROWS; j++) {
if (lakeMap[i][j]) {
liquidType(&deepLiquid, &shallowLiquid, &shallowLiquidWidth);
zeroOutGrid(wreathMap);
fillLake(i, j, deepLiquid, 4, wreathMap, lakeMap);
createWreath(shallowLiquid, shallowLiquidWidth, wreathMap);
if (D_INSPECT_LEVELGEN) {
dumpLevelToScreen();
hiliteGrid(lakeMap, &white, 75);
temporaryMessage("Lake filled.", REQUIRE_ACKNOWLEDGMENT);
}
}
}
}
}
To understand the code completely I think one needs to understand the whole project, though I guess I can make sense out of some of it.