Skip to content

Commit

Permalink
Merge pull request #93 from wheybags/lvlgen
Browse files Browse the repository at this point in the history
level generation for dungeon level 2
  • Loading branch information
wheybags committed Dec 2, 2014
2 parents a1684f2 + 826d912 commit babf6a8
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 76 deletions.
111 changes: 78 additions & 33 deletions apps/freeablo/falevelgen/levelgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,21 +569,44 @@ namespace FALevelGen
}
}

bool placeUpStairs(Level::Dun& level, const std::vector<Room>& rooms)
bool placeUpStairs(Level::Dun& level, const std::vector<Room>& rooms, size_t levelNum)
{
for(size_t i = 0; i < rooms.size(); i++)
if(levelNum == 1)
{
size_t baseX = rooms[i].xPos + (rooms[i].width/2);
size_t baseY = rooms[i].yPos;

if(level[baseX-1][baseY-1] == blank && level[baseX][baseY-1] == blank && level[baseX+1][baseY-1] == blank &&
level[baseX-1][baseY] == wall && level[baseX][baseY] == wall && level[baseX+1][baseY] == wall &&
level[baseX-1][baseY+1] == floor && level[baseX][baseY+1] == floor && level[baseX+1][baseY+1] == floor)
for(size_t i = 0; i < rooms.size(); i++)
{
level[baseX][baseY] = upStairs;
return true;
size_t baseX = rooms[i].xPos + (rooms[i].width/2);
size_t baseY = rooms[i].yPos;

// on a wall
if(level[baseX-1][baseY-1] == blank && level[baseX][baseY-1] == blank && level[baseX+1][baseY-1] == blank &&
level[baseX-1][baseY] == wall && level[baseX][baseY] == wall && level[baseX+1][baseY] == wall &&
level[baseX-1][baseY+1] == floor && level[baseX][baseY+1] == floor && level[baseX+1][baseY+1] == floor)
{
level[baseX][baseY] = upStairs;
return true;
}
}
}
else
{
for(size_t i = 0; i < rooms.size(); i++)
{
if(rooms[i].width >= 6 && rooms[i].height >= 6)
{
size_t baseX = rooms[i].centre().first;
size_t baseY = rooms[i].centre().second;

if(level[baseX][baseY] != floor)
continue;

level[baseX][baseY] = upStairs;

return true;
}
}
}


return false;
}
Expand All @@ -597,6 +620,9 @@ namespace FALevelGen
size_t baseX = rooms[i].centre().first;
size_t baseY = rooms[i].centre().second;

if(level[baseX][baseY] != floor)
continue;

level[baseX][baseY] = downStairs;

return true;
Expand All @@ -621,7 +647,7 @@ namespace FALevelGen
// extra edges to allow for some loops.
// 5. Connect the rooms according to the graph from the last step with l shaped corridoors, and
// also draw any corridoor rooms that the corridoors overlap as part of the corridoor.
Level::Dun generateTmp(size_t width, size_t height)
Level::Dun generateTmp(size_t width, size_t height, size_t levelNum)
{
Level::Dun level(width, height);

Expand Down Expand Up @@ -698,8 +724,8 @@ namespace FALevelGen
addDoors(level, rooms);

// Make sure we always place stairs
if(!(placeUpStairs(level, rooms) && placeDownStairs(level, rooms)))
return generateTmp(width, height);
if(!(placeUpStairs(level, rooms, levelNum) && placeDownStairs(level, rooms)))
return generateTmp(width, height, levelNum);

return level;
}
Expand Down Expand Up @@ -770,20 +796,14 @@ namespace FALevelGen
newVal = tileset.outsideLeftCorner;
}

else if(val == tileset.floor)
{
if(getXY(x, y, tmpLevel) == downStairs)
newVal = downStairs;
}

level[x][y] = newVal;
}

void placeMonsters(Level::Level& level, const DiabloExe::DiabloExe& exe, size_t levelNum)
void placeMonsters(Level::Level& level, const DiabloExe::DiabloExe& exe, size_t dLvl)
{
std::vector<Level::Monster>& monsters = level.getMonsters();

std::vector<const DiabloExe::Monster*> possibleMonsters = exe.getMonstersInLevel(levelNum);
std::vector<const DiabloExe::Monster*> possibleMonsters = exe.getMonstersInLevel(dLvl);

for(size_t i = 0; i < (level.height() + level.width())/2; i++)
{
Expand All @@ -801,21 +821,28 @@ namespace FALevelGen
}
}

Level::Level* generate(size_t width, size_t height, size_t levelNum, const DiabloExe::DiabloExe& exe, const std::string& celPath)
Level::Level* generate(size_t width, size_t height, size_t dLvl, const DiabloExe::DiabloExe& exe)
{
Level::Dun tmpLevel = generateTmp(width, height);
size_t levelNum = ((dLvl-1) / 4) + 1;

Level::Dun tmpLevel = generateTmp(width, height, levelNum);

Level::Dun level(width, height);

std::stringstream ss; ss << "resources/tilesets/l" << levelNum << ".ini";

TileSet tileset(ss.str());

// Fill in isometric information (wall direction, etc), using flat tmpLevel as a base
for(int32_t x = 0; x < (int32_t)width; x++)
{
for(int32_t y = 0; y < (int32_t)height; y++)
{
if(tmpLevel[x][y] == upStairs || tmpLevel[x][y] == downStairs)
{
level[x][y] = tmpLevel[x][y];
continue;
}

if(isWall(x, y, tmpLevel))
{
if(isWall(x+1, y, tmpLevel))
Expand Down Expand Up @@ -852,7 +879,7 @@ namespace FALevelGen
if(tmpLevel[x][y] == blank)
level[x][y] = tileset.blank;
else
setPoint(x, y, tileset.floor, tmpLevel, level, tileset);
level[x][y] = tileset.floor;
}
}
}
Expand Down Expand Up @@ -883,11 +910,17 @@ namespace FALevelGen
}
else if(level[x][y] == downStairs)
{
level[x][y] = tileset.downStairs1;
level[x+1][y] = tileset.downStairs2;

level[x][y-1] = tileset.downStairs3;
level[x+1][y-1] = tileset.downStairs4;
level[x-1][y-1] = tileset.downStairs1;
level[x][y-1] = tileset.downStairs2;
level[x+1][y-1] = tileset.downStairs3;

level[x-1][y] = tileset.downStairs4;
level[x][y] = tileset.downStairs5;
level[x+1][y] = tileset.downStairs6;

level[x-1][y+1] = tileset.downStairs7;
level[x][y+1] = tileset.downStairs8;
level[x+1][y+1] = tileset.downStairs9;

downStairsPoint = std::make_pair(x*2,y*2);
}
Expand All @@ -898,8 +931,20 @@ namespace FALevelGen
}
}

Level::Level* retval = new Level::Level(level, "levels/l1data/l1.til", "levels/l1data/l1.min", "levels/l1data/l1.sol", celPath, downStairsPoint, upStairsPoint, tileset.getDoorMap());
placeMonsters(*retval, exe, levelNum);
ss.str(""); ss << "levels/l" << levelNum << "data/l" << levelNum << ".cel";
std::string celPath = ss.str();

ss.str(""); ss << "levels/l" << levelNum << "data/l" << levelNum << ".til";
std::string tilPath = ss.str();

ss.str(""); ss << "levels/l" << levelNum << "data/l" << levelNum << ".min";
std::string minPath = ss.str();

ss.str(""); ss << "levels/l" << levelNum << "data/l" << levelNum << ".sol";
std::string solPath = ss.str();

Level::Level* retval = new Level::Level(level, tilPath, minPath, solPath, celPath, downStairsPoint, upStairsPoint, tileset.getDoorMap());
placeMonsters(*retval, exe, dLvl);

return retval;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/freeablo/falevelgen/levelgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace DiabloExe
namespace FALevelGen
{

Level::Level* generate(size_t width, size_t height, size_t levelNum, const DiabloExe::DiabloExe& exe, const std::string& celPath);
Level::Level* generate(size_t width, size_t height, size_t dLvl, const DiabloExe::DiabloExe& exe);

}

Expand Down
7 changes: 7 additions & 0 deletions apps/freeablo/falevelgen/tileset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,14 @@ namespace FALevelGen
downStairs1 = pt.get<size_t>("Basic.downStairs1");
downStairs2 = pt.get<size_t>("Basic.downStairs2");
downStairs3 = pt.get<size_t>("Basic.downStairs3");

downStairs4 = pt.get<size_t>("Basic.downStairs4");
downStairs5 = pt.get<size_t>("Basic.downStairs5");
downStairs6 = pt.get<size_t>("Basic.downStairs6");

downStairs7 = pt.get<size_t>("Basic.downStairs7");
downStairs8 = pt.get<size_t>("Basic.downStairs8");
downStairs9 = pt.get<size_t>("Basic.downStairs9");

loadDoorMap(pt);
}
Expand Down
7 changes: 7 additions & 0 deletions apps/freeablo/falevelgen/tileset.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ namespace FALevelGen
size_t downStairs1;
size_t downStairs2;
size_t downStairs3;

size_t downStairs4;
size_t downStairs5;
size_t downStairs6;

size_t downStairs7;
size_t downStairs8;
size_t downStairs9;

size_t getRandomTile(size_t tile);
std::map<size_t, size_t> getDoorMap();
Expand Down
61 changes: 25 additions & 36 deletions apps/freeablo/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,49 +82,38 @@ void mouseMove(size_t x, size_t y)
yClick = y;
}

void setLevel(size_t levelNum, const DiabloExe::DiabloExe& exe, FAWorld::World& world, FARender::Renderer& renderer, Level::Level* level)
void setLevel(size_t dLvl, const DiabloExe::DiabloExe& exe, FAWorld::World& world, FARender::Renderer& renderer, Level::Level* level)
{
world.clear();
renderer.setLevel(level);
world.setLevel(*level, exe);

if(levelNum == 0)
if(dLvl == 0)
world.addNpcs(exe);
}

Level::Level* getLevel(size_t levelNum, const DiabloExe::DiabloExe& exe)
Level::Level* getLevel(size_t dLvl, const DiabloExe::DiabloExe& exe)
{
switch(levelNum)
if(dLvl == 0)
{
case 0:
{
Level::Dun sector1("levels/towndata/sector1s.dun");
Level::Dun sector2("levels/towndata/sector2s.dun");
Level::Dun sector3("levels/towndata/sector3s.dun");
Level::Dun sector4("levels/towndata/sector4s.dun");

return new Level::Level(Level::Dun::getTown(sector1, sector2, sector3, sector4), "levels/towndata/town.til",
"levels/towndata/town.min", "levels/towndata/town.sol", "levels/towndata/town.cel", std::make_pair(25,29), std::make_pair(75,68), std::map<size_t, size_t>());

break;
}

case 1:
{
return FALevelGen::generate(100, 100, levelNum, exe, "levels/l1data/l1.cel");
break;
}
Level::Dun sector1("levels/towndata/sector1s.dun");
Level::Dun sector2("levels/towndata/sector2s.dun");
Level::Dun sector3("levels/towndata/sector3s.dun");
Level::Dun sector4("levels/towndata/sector4s.dun");

case 2:
case 3:
case 4:
{
std::cerr << "level not supported yet" << std::endl;
break;
}
return new Level::Level(Level::Dun::getTown(sector1, sector2, sector3, sector4), "levels/towndata/town.til",
"levels/towndata/town.min", "levels/towndata/town.sol", "levels/towndata/town.cel", std::make_pair(25,29), std::make_pair(75,68), std::map<size_t, size_t>());
}
else if(dLvl < 9)
{
return FALevelGen::generate(100, 100, dLvl, exe);
}
else
{
std::cerr << "level not supported yet" << std::endl;
exit(1);
return NULL;
}

return NULL;
}

/**
Expand All @@ -138,7 +127,7 @@ bool parseOptions(int argc, char** argv, bpo::variables_map& variables)
desc.add_options()
("help,h", "Print help")
// -1 represents the main menu
("level,l", bpo::value<int32_t>()->default_value(-1), "Level number to load (0-4)");
("level,l", bpo::value<int32_t>()->default_value(-1), "Level number to load (0-16)");

try
{
Expand All @@ -152,8 +141,8 @@ bool parseOptions(int argc, char** argv, bpo::variables_map& variables)

bpo::notify(variables);

const int32_t levelNum = variables["level"].as<int32_t>();
if(levelNum > 4)
const int32_t dLvl = variables["level"].as<int32_t>();
if(dLvl > 16)
throw bpo::validation_error(
bpo::validation_error::invalid_option_value, "level");
}
Expand Down Expand Up @@ -321,7 +310,7 @@ void runGameLoop(const bpo::variables_map& variables)

FALevelGen::FAsrand(time(NULL));

std::vector<Level::Level*> levels(5);
std::vector<Level::Level*> levels(9);

int32_t currentLevel = variables["level"].as<int32_t>();

Expand Down Expand Up @@ -405,7 +394,7 @@ void runGameLoop(const bpo::variables_map& variables)
currentLevel = tmp;

if(levels[currentLevel] == NULL)
levels[currentLevel] = getLevel(currentLevel == 0 ? 0 : 1, exe);
levels[currentLevel] = getLevel(currentLevel, exe);

level = levels[currentLevel];

Expand Down
2 changes: 2 additions & 0 deletions components/cel/celfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ namespace Cel
std::string palFilename;
if(Misc::StringUtils::endsWith(filename, "l1.cel"))
palFilename = Misc::StringUtils::replaceEnd("l1.cel", "l1.pal", filename);
else if(Misc::StringUtils::endsWith(filename, "l2.cel"))
palFilename = Misc::StringUtils::replaceEnd("l2.cel", "l2.pal", filename);
else
palFilename = "levels/towndata/town.pal";

Expand Down
19 changes: 13 additions & 6 deletions resources/tilesets/l1.ini
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,18 @@ upStairs7 = 13
upStairs8 = 67
upStairs9 = 68

# downStairs values define a 2x2 block for stairs down
downStairs1 = 59
downStairs2 = 60
downStairs3 = 57
downStairs4 = 58
# downStairs values define a 3x3 block for stairs down
downStairs1 = 57
downStairs2 = 58
downStairs3 = 13

downStairs4 = 59
downStairs5 = 60
downStairs6 = 13

downStairs7 = 13
downStairs8 = 13
downStairs9 = 13

# Map of closed door til entries to open door til entries
[DoorMap]
Expand All @@ -53,7 +60,7 @@ downStairs4 = 58
# normal shows the percentage of tiles that will be the
# normal value from the Basic section, all others are of the format
# "index = weight", where weight adjusts it's frequency relative to the others
# No section for a block just mean it will always be the "basic" version
# No section for a block just means it will always be the "basic" version
[XWall]
normal = 75
97 = 33
Expand Down
Loading

0 comments on commit babf6a8

Please sign in to comment.