Here's a few ideas about how to improve the replayability, diversity, and unexpectedness of procedurally generated levels. These ideas have all been tested in my latest roguelike (*) and I think they can apply to
any procedurally generated level or world since they're not so much about specific algorithms as they are about changing existing algorithms.
Tweak the variables. Before you generate a level or world, semi-randomize the variables you use to create it. This is the easiest way I can think of changing how the level is built.
For example, if you use one of the "place a room or corridor until the map is full" algorithms, then you can change how often you add corridors and how full a map needs to be until it's considered full. A level with corridorChance = 98% and isConsideredFullPercent = 33 will make a sewer-like level with a bunch of corridors but a level with corridorChance = 10% and isConsideredFullPercent = 90 will make a level that is cram packed with rooms. You may find that certain values make the kind of levels you like best but adding some variation can surprise you and hopefully change the experience of whoever is playing. So, sticking with the same example, instead of hard coding corridorChance = 25% and isConsideredFullPercent = 25, try it with corridorChance = [20% to 80%] and isConsideredFullPercent = 50 + [-25 to 25].
You could try tweaking variables for the likelihood of magic items, traps, out of depth monsters, huge rooms, poisonous traps and creatures, puzzles, piles of gold, how much gold is in each pile, pretty much anything really really.
Tweak the lists. I guess this is technically a subclass of tweaking the variables, but I think this technique is different enough to stand out on it's own. Basically; if your algorithms include collections of things to chose from, try changing those collections before you run the algorithms.
For example; if you have a list of room types that are randomly assigned to each room in a level, then try changing the list before you generate each level: remove a few types so they don't appear on this level and add duplicates of some types so they are more likely to appear. I image this like having a deck of options and by removing some options and having others appear more or less often than others, you can change how likely those options are. So, instead of saying your DwarfFortress level has 2 stockpile rooms, 2 trap rooms, 6 houses, 2 empty rooms, tweak the list so you may end up with variations like:
4 stockpile rooms, 4 trap rooms, 2 houses, 2 empty rooms
3 stockpile rooms, 3 trap rooms, 3 houses 3 workshop rooms
2 stockpile rooms, 2 trap rooms 4 empty rooms, 2 workshop rooms
2 stockpile rooms, 2 houses, 2 empty rooms, 4 workshop rooms
6 trap rooms, 2 houses, 2 empty rooms, 2 workshop rooms
If you have an even larger starting list then you can come up with even more variety. By removing items from your collections you also ensure that the player will need to play several times before they see everything. These lists don't need to just be room types either - they could be lists of loot, creatures, room shapes, alters, or practically anything you can think of.
Add explicit variations. This is a generalization of the other two. It adds the most flexibility but also involves the most work for the developer and possibly the player since they may need to know what variations are in play. For this technique, create a list of explicit changes to the core game and add a few at random. These changes can be small or large (undead get 1 extra hp vs undead get 50 extra hp), specific or general (followers of Cthulhu gain 5 attack when underground vs all creatures regenerate 1 additional hp per turn). Simply pick a few, or a lot, and add them. Some of the combinations may be wildly unfair but as long as there are ways of mitigating most misfortunes, it should always be fair enough. Perhaps.
A neat side effect of this is that it's sort of like having to identify items in that the player will have to identify what the
rules are since they may be different from one game to another.
These are some general ways that I've tried to improve the procedural algorithms I've used. What do you think of them? What ways have you used or thought of?
(*) My latest roguelike was Pugnacious Wizards 2. The rogue basin page is at
http://roguebasin.roguelikedevelopment.org/index.php?title=Pugnacious_Wizards_2 and I have a blog post that explains how these were implemented in the game at
http://trystans.blogspot.com/2013/10/worldgen-and-dungeon-variations-in.html.